How to interpret multiple XSD key/keyref on an XML attribute - xsd

Given the following XML element structure:
<a>
<b>
<c test_id="1"/>
<d test_ref="1"/>
</b>
<e>
<c test_id="12"/>
</e>
<a>
and the following XSD rules:
-) in Element a:
<xsd:key name="key_A">
<xsd:selector xpath=".//c"/>
<xsd:field xpath="#test_id"/>
</xsd:key>
<xsd:keyref name="keyref_A" refer="key_A"">
<xsd:selector xpath=".//d"/>
<xsd:field xpath="test_id"/>
</xsd:keyref>
-) in Element b:
<xsd:key name="key_B">
<xsd:selector xpath=".//c"/>
<xsd:field xpath="#test_id"/>
</xsd:key>
<xsd:keyref name="keyref_B" refer="key_B"">
<xsd:selector xpath=".//d"/>
<xsd:field xpath="test_id"/>
</xsd:keyref>
When I set test_ref to "12" I get a validation error.
When I set test_ref to "1" I get no error.
How are multiple keys/keyrefs interpreted? Does every keyref needs to be valid? Do I get not error when I set it to "1" because it satisfies both keys?
There are already questions regarding this topic but none explains how it is evaluated by a parser.

Related

Search with queries constrained to elements using search:search

What i want to do is similar in the following link but we want it using search:search:
Queries Constrained to Elements
Basically we have 2 xmls like the following:
XML-1
<rootElement>
<id>7635940284725382300</id>
<parentElement>
<childElement1>ce1-A</childElement1>
<childElement2>ce2-1</childElement2>
</parentElement>
<parentElement>
<childElement1>ce1-B</childElement1>
<childElement2>ce2-2</childElement2>
</parentElement>
<parentElement>
<childElement1>ce1-C</childElement1>
<childElement2>ce2-3</childElement2>
</parentElement>
</rootElement>
XML-2
<rootElement>
<id>7635940284725382398</id>
<parentElement>
<childElement1>ce1-A</childElement1>
<childElement2>ce2-2</childElement2>
</parentElement>
<parentElement>
<childElement1>ce1-B</childElement1>
<childElement2>ce2-3</childElement2>
</parentElement>
<parentElement>
<childElement1>ce1-C</childElement1>
<childElement2>ce2-4</childElement2>
</parentElement>
</rootElement>
So now what i want to do is to have a match for childElement1 and childElement2 within the same parentElement.
For example:
If i search with values childElement1 = ce1-B and childElement2 = ce2-3, it should only give me XML-2 and not return XML-1.
We have achieved this using the cts:search query as explained in the link:
cts:search (/,
cts:element-query (
xs:QName ('parentElement'),
cts:and-query ((
cts:element-value-query(xs:QName('childElement1'), 'ce1-B', 'exact'),
cts:element-value-query(xs:QName('childElement2'), 'ce2-3', 'exact')
))
)
)
Question:
We are using search:search with different search:constraints? I have read about using container for this but there are no good examples to show how it can be used.
Here is our sample search:search, so need to tweak this to have the same functionality as that shown by cts:search query shown above:
import module namespace search = "http://marklogic.com/appservices/search" at "/MarkLogic/appservices/search/search.xqy";
search:search("childElement1:ce1-B AND childElement2:ce2-3 sort:childElement2ASC"
, <options xmlns="http://marklogic.com/appservices/search">
<term>
<term-option xmlns="http://marklogic.com/appservices/search">unstemmed</term-option>
<empty apply="all-results" />
<term-option>case-insensitive</term-option>
<term-option>wildcarded</term-option>
</term>
<transform-results apply="transformed-result" ns="http://isearchgui/search" at="/customResultSet.xqy" />
<search:constraint name="childElement1">
<search:range type="xs:string" facet="false" collation="http://marklogic.com/collation/en">
<search:path-index ns="http://my.search.com/something">//childElement1</search:path-index>
</search:range>
</search:constraint>
<search:constraint name="childElement2">
<search:range type="xs:string" facet="false" collation="http://marklogic.com/collation/en">
<search:path-index ns="http://my.search.com/something">//childElement2</search:path-index>
</search:range>
</search:constraint>
<search:operator name="sort">
<search:state name="childElement1ASC">
<search:sort-order direction="ascending" type="xs:string">
<search:path-index ns="http://my.search.com/something">//childElement1</search:path-index>
</search:sort-order>
</search:state>
<search:state name="childElement1DES">
<search:sort-order direction="descending" type="xs:string">
<search:path-index ns="http://my.search.com/something">//childElement1</search:path-index>
</search:sort-order>
</search:state>
<search:state name="childElement2ASC">
<search:sort-order direction="ascending" type="xs:string">
<search:path-index ns="http://my.search.com/something">//childElement2</search:path-index>
</search:sort-order>
</search:state>
<search:state name="childElement2DES">
<search:sort-order direction="descending" type="xs:string">
<search:path-index ns="http://my.search.com/something">//childElement2</search:path-index>
</search:sort-order>
</search:state>
</search:operator>
</options>
, 0
, 15);
Hope this helps to answer.
You are on the right track. Use the container option, which works like any other constraint option, then wrap your nested query in parenthesis.
For example:
search:parse('contain:(test one two)',
<options xmlns="http://marklogic.com/appservices/search">
<constraint name="contain">
<container>
<element ns="" name="parentElement"/>
</container>
</constraint>
</options>)
=>
<cts:element-query xmlns:cts="http://marklogic.com/cts">
<cts:element>parentElement</cts:element>
<cts:and-query>
<cts:word-query>
<cts:text xml:lang="en">test</cts:text>
</cts:word-query>
<cts:word-query>
<cts:text xml:lang="en">one</cts:text>
</cts:word-query>
<cts:word-query>
<cts:text xml:lang="en">two</cts:text>
</cts:word-query>
</cts:and-query>
</cts:element-query>
So in your case you would have the main-search string as :
search:search('contain:(childElement1:ce1-B AND childElement2:ce2-3) sort:childElement2ASC', <options ....)

XSD Schema - unable to add annotation in simple type

I have a problem with schema and annotation for simpleType.
My schema:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
/...CODE.../
<xsd:simpleType name="DateTimeType">
<xsd:restriction base="xsd:dateTime"/>
<xsd:annotation> <!--Line: 161 -->
<xsd:documentation>
Date time
</xsd:documentation>
</xsd:annotation>
</xsd:simpleType>
</xsd:schema>
My error
lineNumber: 161; columnNumber: 25; s4s-elt-must-match.1: The content
of 'simpleType' must match (annotation?, (restriction | list | union)).
A problem was found starting at: annotation.
How can I fix it ?
Regards
Ok, I fixed it. What is important: the order of elements in exaple simple type. So, good order is annotation, and then e.q. restriction or union.
<xsd:simpleType name="DateTimeType">
<xsd:annotation>
<xsd:documentation>
Date time
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:dateTime"/>
</xsd:simpleType>

XSD keyref or number literal

Is it possible to define a type which can be either a keyref or a number literal? Just like in any typed programming language you can assign either a number literal OR the name of another variable to a numeric variable. I'm making a schema to define drawing api elements (for another programming language) and would like to define a color type that can either be a hexadecimal literal (such as 0xFF0000 for bright red) OR be a reference to a color defined elsewhere. So you could do (in a XML document):
<color key="dialogBorder1">0x222222</color>
<color key="dialogFill1">0xCCCCCC</color>
<!-- later... -->
<windowTheme name="warningWindow">
<border>
<color>0xFF0000</color> <!-- defined literally -->
</border>
<fill>
<solid>
<color>dialogFill1</color> <!-- defined by keyref -->
</solid>
</fill>
</windowTheme>
If it were possible to impose a choice restriction on attributes I could do something like the following, but I am under the impression this is not possible with current (1.0) version of XSD spec.
<!-- I wish: -->
<xs:complexType name="colorType" >
<xs:attrchoice>
<xs:attribute name="value" type="HexLiteral" /> <!-- literal -->
<xs:attribute name="ref" type="xs:string" /> <!-- keyref (defined elsewhere) -->
</xs:attrchoice>
</xs:complexType>
Which would allow either lieral value or keyref ref:
<color value="0xFF0000" /> <!-- OK -->
<color ref="dialogBorder1" /> <!-- OK -->
But not both:
<color value="0xFF0000" ref="colorXYZ" /> <!-- NOT OK -->
The post is somewhat inconsistent in what's describing. The first XML shows color used without attributes, then the xsd for colorType goes off with some attributes. I assume the XML is what you wanted.
So the following works for:
To define a color type that can either be a hexadecimal literal (such as 0xFF0000 for bright red) OR be a reference to a color defined elsewhere
<xsd:simpleType name="ColorHex">
<xsd:union memberTypes="xsd:string">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="0x[0-9a-fA-F]{6}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>
The above uses the same pattern as the Color type in XHTML (I am showing this to give you sources of inspiration):
<!-- sixteen color names or RGB color expression-->
<xsd:simpleType name="Color">
<xsd:union memberTypes="xsd:NMTOKEN">
<xsd:simpleType>
<xsd:restriction base="xsd:token">
<xsd:pattern value="#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>
The idea here is to use a union. The downside may be that since all that's not matching the HEX pattern will be matched by the string, invalid HEX syntax (e.g. missing digits) will pass through as references.
Other downsides may be in how well is xsd:union supported by the programming languages that you're targeting.

How to define a 'literal' in XSD

I'm a newbie with XSD and pretty much at wits end.
What I need to do is somehow define a 'literal' element within an XSD file so that users can use it in an XML document.
For example:
In the XML document, I want to let a user be able to add an element like this:
<WordBoundary/>
but let the XSD file define not only the name 'WordBoundary' but also a list of Elements within which are of types defined elsewhere within the XSD.
Is this possible?
Updated to provide more information:
I am trying to write an XSD (or set of XSDs) which provide a library of pre-defined elements for an end-user to use.
The elements will ultimately be used to generate a Regular Expression but I want to hide the complexities of regular expressions from users as far as possible.
The XSD will use .NETs XSD.Exe to generate C# classes.
Currently I have defined elements like and and etc. which work fine but rely on their ultimate regex pattern being defined in code. Some of the elements have a Pattern attribute to allow fine tuning but this clutters up the XML document for users somewhat.
Examples of the built-up existing C# definitions:
const string BidMatch = #"(?<" + BidGroupName + ">" + DecimalNumberFragment + ")";
const string OfferMatch = #"(?<" + OfferGroupName + ">" + DecimalNumberFragment + ")";
const string BidOfferSpreadMatch = BidMatch + OptionalGap + RangeSeparatorFragment + OptionalGap + OfferMatch;
I therefore wanted to be able to refactor this so that all the regex patterns are moved from code into XSD definitions to form a library (or if it turns out not to be possible an XML file looked up by name) whereby there are primitives such as and and commonly-used but more complex structures such as etc.
So the use can use predefined elements like directly within their XML document but also be able to build up their own like this:
<Group captureName="MyCustomMatch">
<WordBoundary/>
<Digit/>
<Literal pattern="[xyz]" />
<AnyOf/>
<AnyOfChoice>
<DecimalNumber />
<Gap />
<DecimalNumber />
</AnyOfChoice>
<AnyOfChoice>
<LiteralText text="(" />
<DecimalNumber />
<LiteralText text=")" />
</AnyOfChoice>
<WordBoundary/>
</Group>
(In fact the prefined elements in the library would be build up the same way)
From the code point of view, I currently have AnyOf/Group etc. working by looking at the element type and calling a method to generate the pattern. For this to work, all these new Elements need to have a common ancestor, e.g. RegexLiteral, from which I can just read the Pattern attribute or whatever and add it into the full pattern.
I have tried extending a common type and trying to override its Pattern attribute to use a fixed attribute but XSD does not apparently allow this.
I am hoping this is just a limitation of my XSD knowledge rather than of XSD itself and hoping you clever guys know a way of achieving this.
Update2:
Thought I had it with this XSD fragment
<xs:complexType name="LiteralFragment" abstract="true">
<xs:attribute name="Pattern" type="xs:string" />
</xs:complexType>
<xs:complexType name="Fred">
<xs:complexContent >
<xs:extension base="LiteralFragment" >
<xs:attribute name="Pattern" type="xs:string" fixed="BBB" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
but XSD (and Xsd2Code for that matter) generate this rubbish code:
public partial class Fred : LiteralFragment
{
private string pattern1Field;
public Fred()
{
this.pattern1Field = "BBB";
}
[System.Xml.Serialization.XmlAttributeAttribute("Pattern")]
public string Pattern1
{
get { return this.pattern1Field; }
set { this.pattern1Field = value; }
}
}
which bombs because there are two XmlAttributeAttribute with "Pattern" being used.
What I need is an XSD generator that is intelligent enough to realise this and generate this code instead:
public partial class Fred : LiteralFragment
{
public Fred()
{
Pattern = "BBB";
}
}
Try this....
The XSD:
<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com)-->
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="root" type="TRoot"/>
<xsd:element name="WordBoundary">
<xsd:complexType/>
</xsd:element>
<xsd:element name="SomethingElse">
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="TRoot">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
And this XML:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SomethingElse>Text <WordBoundary/> another <WordBoundary/>...</SomethingElse>
</root>
Is this what you had in mind?

xsd validation ERROR with both minOccurs and length used simultaneously

<xsd:element name="CurrencyCode" minOccurs="0" type="xsd:string">
<xsd:simpleType>
<xsd:restriction>
<xsd:length value="3"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
I want my Currencycode to be an optional value and if at all there is a value it should have a length of 3 letters .. either my CurrencyCode can have Length=0 or length=3
When i use the above code the validator returns an error when there is an empty field
So how can i deal with this ??
Have not tried this (do not have suitable env set up on this machine) but according to the specification you can do as follows:
<xsd:element name="CurrencyCode" minOccurs="0" type="xsd:string">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:pattern value="(?:^$|\w{3})"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
Regular expression (?:^$|\w{3}) matches either empty string or exactly three word characters. You can use (?:^$|[A-Z]{3}) in case you want to accept currency codes only in upper case.

Resources