I wish to share little information here, about Apache Xerces-J's implementation of XML Schema (XSD) 1.1 'type alternatives'.
The XSD 1.1 specification, defines a particular subset of XPath 2.0 language that can be used as value of 'test' attribute of XSD 1.1 <alternative> element. The XSD 1.1 language's XPath 2.0 subset is much smaller than the whole XPath 2.0 language. The specification of this smaller CTA XPath subset, can be read at https://www.w3.org/TR/xmlschema11-1/#coss-ta (specifically, the section mentioning '2.1 It conforms to the following extended BNF' which has grammar specification for the CTA XPath subset).
In fact, the XSD 1.1 specification allows XSD validators, implementing XSD 1.1's <alternative> element, to support a bigger set of XPath 2.0's features (commonly the full XPath 2.0 language) than what is defined by XSD 1.1 CTA (conditional type alternatives) XPath subset.
For XSD 1.1 CTAs, Xerces-J with user option, allows selecting either:
1) The smaller XPath subset (the default for Xerces-J), or
2) Full XPath 2.0. How selecting between XPath subset or the full XPath 2.0 language, can be done for Xerces-J's CTA implementation is described here, https://xerces.apache.org/xerces2-j/faq-xs.html#faq-3.
I've analyzed a bit, the nature of XSD 1.1 CTA XPath subset language. Following are essentially the main XSD 1.1 CTA XPath subset patterns, that may be used within XSD 1.1 schemas when using XSD <alternative> element,
1) Using comparators (like >, <, =, !=, <=, >=):
The example CTA XPath expressions are following,
@x = @y,
@x = 3,
@x != 3,
@x > @y
2) Using comparators with logical operators:
The example CTA XPath expressions are following,
(@x = @y) or (@p = @q),
((1 = 2) or (5 = 6)) and (5 = 7),
(1 and 2) or (5 and 7)
3) Using XPath 2.0 'not' function:
An example XPath expression is following,
(@x = @y) and not(@p)
Interestingly, the XSD 1.1 CTA XPath subset language, allows using only the XPath 2.0 fn:not function and no other XPath 2.0 built-in functions. Constructor functions, for all built-in XSD types may be used, for e.g xs:integer(..), xs:boolean(..) etc, in XSD 1.1 CTA XPath subset expressions.
As per the XSD 1.1 specification, during XSD 1.1 CTA evaluations, the XML element and attribute nodes are untyped (i.e the XML nodes do not carry any type annotation coming from a XML schema). Therefore, in many cases, XSD 1.1 CTA XPath subset expressions when used with Xerces-J need to use explicit casts (for e.g, <xs:alternative test="(xs:integer(@x) = xs:integer(@y)) and fn:not(xs:boolean(@p))"> with namespace prefix 'fn' bound to the URI 'http://www.w3.org/2005/xpath-functions'). For the CTA XPath subset language or the full XPath 2.0 language for CTAs, it is optional for the XPath expressions to have the "fn" prefix with the XPath built-in functions. Typically, XML schema authors would not use the "fn" prefix for XPath built-in functions.
Saturday, March 21, 2020
Tuesday, March 10, 2020
XML Schema 1.1 <assert> continued ...
This blog post is related to the XML Schema (XSD) use case that I've discussed within my previous two blog posts. Consider the following XML Schema 1.1 document, having an XSD <assert> element,
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:sequence>
<xs:element name="isSeqTwo" type="xs:boolean"/>
<xs:choice>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="p" type="xs:string"/>
<xs:element name="q" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="x" type="xs:string"/>
<xs:element name="y" type="xs:string"/>
</xs:sequence>
</xs:choice>
</xs:sequence>
<xs:assert test="if (isSeqTwo = true()) then p else not(p)"/>
</xs:complexType>
</xs:element>
</xs:schema>
The above schema document, is different than my earlier schema documents that I've presented within my previous two blog posts, in following way:
The XML child content model of an element "X", is a sequence of an element followed by a choice.
Within the earlier two blog posts that I've presented, the XML child content model of element "X" is dependent on the value of an attribute on an element "X", which could be enforced using either an XSD 1.1 <assert> or an <alternative>.
Few XML instance documents that are valid or invalid, according to the above XSD schema document are following:
Valid,
<X>
<isSeqTwo>0</isSeqTwo>
<x>string1</x>
<y>string2</y>
</X>
Valid,
<X>
<isSeqTwo>1</isSeqTwo>
<p>string1</p>
<q>string2</q>
</X>
Invalid,
<X>
<isSeqTwo>1</isSeqTwo>
<x>string1</x>
<y>string2</y>
</X>
The XSD use case illustrated above, is useful and could only be accomplished using an XSD 1.1 <assert> element.
As a side discussion, to re-affirm I would like to cite from the XML Schema 1.1 structures specification the following rules: 3.4.4.2 Element Locally Valid (Complex Type) that say,
For an element information item E to be locally ·valid· with respect to a complex type definition T all of the following must be true:
1
2
3
...
6 E is ·valid· with respect to each of the assertions in T.{assertions} as per Assertion Satisfied (§3.13.4.1).
We can infer, from the above rules from XSD 1.1 spec, that an XML instance element is valid according to a XSD complex type definition, if an XML instance element is valid with respect to each of the assertions present on the complex type with which an XML instance element is validated, in addition to other XSD complex type validation rules.
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:sequence>
<xs:element name="isSeqTwo" type="xs:boolean"/>
<xs:choice>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="p" type="xs:string"/>
<xs:element name="q" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="x" type="xs:string"/>
<xs:element name="y" type="xs:string"/>
</xs:sequence>
</xs:choice>
</xs:sequence>
<xs:assert test="if (isSeqTwo = true()) then p else not(p)"/>
</xs:complexType>
</xs:element>
</xs:schema>
The above schema document, is different than my earlier schema documents that I've presented within my previous two blog posts, in following way:
The XML child content model of an element "X", is a sequence of an element followed by a choice.
Within the earlier two blog posts that I've presented, the XML child content model of element "X" is dependent on the value of an attribute on an element "X", which could be enforced using either an XSD 1.1 <assert> or an <alternative>.
Few XML instance documents that are valid or invalid, according to the above XSD schema document are following:
Valid,
<X>
<isSeqTwo>0</isSeqTwo>
<x>string1</x>
<y>string2</y>
</X>
Valid,
<X>
<isSeqTwo>1</isSeqTwo>
<p>string1</p>
<q>string2</q>
</X>
Invalid,
<X>
<isSeqTwo>1</isSeqTwo>
<x>string1</x>
<y>string2</y>
</X>
The XSD use case illustrated above, is useful and could only be accomplished using an XSD 1.1 <assert> element.
As a side discussion, to re-affirm I would like to cite from the XML Schema 1.1 structures specification the following rules: 3.4.4.2 Element Locally Valid (Complex Type) that say,
For an element information item E to be locally ·valid· with respect to a complex type definition T all of the following must be true:
1
2
3
...
6 E is ·valid· with respect to each of the assertions in T.{assertions} as per Assertion Satisfied (§3.13.4.1).
We can infer, from the above rules from XSD 1.1 spec, that an XML instance element is valid according to a XSD complex type definition, if an XML instance element is valid with respect to each of the assertions present on the complex type with which an XML instance element is validated, in addition to other XSD complex type validation rules.
Sunday, March 1, 2020
XML Schema 1.1 <alternative> use cases with <choice> and <attribute>
While using XML Schema (XSD) 1.1, many times when we use XSD 1.1 <assert> we could find a solution using XSD 1.1 <alternative> as well for the same use cases (and vice versa as well). This is usually the case, when the XML child content model of an element, is dependent on the values of attributes of an element on which the attributes appear. This is evident for the first example, of my previous blog post. Given the same XML input examples, as in the first example of my previous blog post, the following XML Schema 1.1 example using <alternative> is also a possible solution,
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:alternative test="xs:boolean(@isB) eq true()">
<xs:complexType>
<xs:sequence>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
<xs:attribute name="isB" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:alternative>
<xs:alternative>
<xs:complexType>
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
<xs:attribute name="isB" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:alternative>
</xs:element>
</xs:schema>
Then the question arises, for these same use cases should we use XSD 1.1 <assert> or an <alternative>? Below are the pros and cons for this, according to me:
1) An XSD 1.1 solution, using <assert> has less lines of code than the one using <alternative>, which many would consider as a benefit.
2) I personally, prefer an XPath expression '@isB = true()' (within 'if (@isB = true()) then b else not(b)') of an <assert> over 'xs:boolean(@isB) eq true()' in an <alternative>. With these examples, for the example involving <alternative> an attribute node 'isB' has a type annotation of xs:untypedAtomic that requires an explicit cast with xs:boolean(..). I tend to prefer, the XPath expressions that don't use explicit casts (since, such XPath expressions look more schema aware).
3) One of the benefits, I see with the solution using an XSD 1.1 <alternative> over <assert>, is better error diagnostics in case of XML validation errors.
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:alternative test="xs:boolean(@isB) eq true()">
<xs:complexType>
<xs:sequence>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
<xs:attribute name="isB" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:alternative>
<xs:alternative>
<xs:complexType>
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
<xs:attribute name="isB" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:alternative>
</xs:element>
</xs:schema>
Then the question arises, for these same use cases should we use XSD 1.1 <assert> or an <alternative>? Below are the pros and cons for this, according to me:
1) An XSD 1.1 solution, using <assert> has less lines of code than the one using <alternative>, which many would consider as a benefit.
2) I personally, prefer an XPath expression '@isB = true()' (within 'if (@isB = true()) then b else not(b)') of an <assert> over 'xs:boolean(@isB) eq true()' in an <alternative>. With these examples, for the example involving <alternative> an attribute node 'isB' has a type annotation of xs:untypedAtomic that requires an explicit cast with xs:boolean(..). I tend to prefer, the XPath expressions that don't use explicit casts (since, such XPath expressions look more schema aware).
3) One of the benefits, I see with the solution using an XSD 1.1 <alternative> over <assert>, is better error diagnostics in case of XML validation errors.
Saturday, February 15, 2020
XML Schema 1.1 <assert> use cases with <choice> and <attribute>
I've been imagining that, what could be useful use cases of XML Schema (XSD) 1.1 <assert> construct.
According to the XSD 1.1 structures specification, "assertion components constrain the existence and values of related XML elements and attributes".
One of useful use cases possible for XSD 1.1 <assert> is, to constrain the standard behavior of XSD 1.0 / 1.1 <choice> construct. I'll attempt to write something about this, here on this blog post.
Below is an XSD schema example using the <choice> construct, that is correct for both 1.0 and 1.1 versions of XSD language:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The above schema document, ensures that following XML instance documents would be valid:
<X>
<a>some string</a>
</X>
,
<X>
<b>some string</b>
</X>
,
<X>
<c>some string</c>
</X>
(essentially showing that, element 'X' can have only one of the elements 'a', 'b' or 'c' as a child element)
Lets see how the above XSD example, can be made a little different using XSD elements <attribute> and <assert>. Below is such a modified XSD document,
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
<xs:attribute name="isB" type="xs:boolean" use="required"/>
<xs:assert test="if (@isB = true()) then b else not(b)"/>
</xs:complexType>
</xs:element>
</xs:schema>
The complete meaning of above XSD document is following,
1) The <choice> with three <element> declarations below it, essentially are the same constraints as the earlier XSD document has shown.
2) This schema additionally specifies, a mandatory boolean typed attribute named 'isB'.
3) The <assert> specifies that, if value of attribute 'isB' is true then element 'b' must be present as a child of element 'X'. If value of attribute 'isB' is false, then element 'X' cannot have element 'b' as its child but one of elements 'a' or 'c' would be a valid child of element 'X'.
The following XML instance documents would be valid according to above mentioned XSD document:
<X isB="1">
<b>some string</b>
</X>
,
<X isB="0">
<a>some string</a>
</X>
,
<X isB="0">
<c>some string</c>
</X>
And, the following XML instance documents would be invalid according to the same XSD document:
<X isB="0">
<b>some string</b>
</X>
,
<X isB="1">
<a>some string</a>
</X>
,
<X isB="0">
<d>some string</d>
</X>
Now lets consider another XSD example, where the schema document specifies a choice between three or more sequences. Below is mentioned such a schema document:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="p" type="xs:string"/>
<xs:element name="q" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="x" type="xs:string"/>
<xs:element name="y" type="xs:string"/>
</xs:sequence>
</xs:choice>
<xs:attribute name="isSeqTwo" type="xs:boolean" use="required"/>
<xs:assert test="if (@isSeqTwo = true()) then p else not(p)"/>
</xs:complexType>
</xs:element>
</xs:schema>
The complete meaning of above XSD document is following,
1) A <choice> is specified between three <sequence> elements. Therefore, element 'X' can have one of following sequences as its child: {a, b}, {p, q} or {x, y}.
2) This schema additionally specifies, a mandatory boolean typed attribute named 'isSeqTwo'.
3) The <assert> specifies that, if value of attribute 'isSeqTwo' is true then sequence {p, q} must be present as a child of element 'X'. If value of attribute 'isSeqTwo' is false, then element 'X' cannot have sequence {p, q} as its child but one of sequences {a, b} or {x, y} would be a valid child of element 'X'.
The following XML instance documents would be valid according to above mentioned XSD document:
<X isSeqTwo="1">
<p>string1</p>
<q>string2</q>
</X>
,
<X isSeqTwo="0">
<a>string1</a>
<b>string2</b>
</X>
,
<X isSeqTwo="0">
<x>string1</x>
<y>string2</y>
</X>
And, the following XML instance documents would be invalid according to the same XSD document:
<X isSeqTwo="0">
<p>string1</p>
<q>string2</q>
</X>
,
<X isSeqTwo="1">
<a>string1</a>
<b>string2</b>
</X>
,
<X isSeqTwo="0">
<i>string1</i>
<j>string2</j>
</X>
All the above examples, and any other XSD 1.0/1.1 constructs may be used with any standards compliant XSD validator.
That's about all I wanted to say, about this topic.
According to the XSD 1.1 structures specification, "assertion components constrain the existence and values of related XML elements and attributes".
One of useful use cases possible for XSD 1.1 <assert> is, to constrain the standard behavior of XSD 1.0 / 1.1 <choice> construct. I'll attempt to write something about this, here on this blog post.
Below is an XSD schema example using the <choice> construct, that is correct for both 1.0 and 1.1 versions of XSD language:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
The above schema document, ensures that following XML instance documents would be valid:
<X>
<a>some string</a>
</X>
,
<X>
<b>some string</b>
</X>
,
<X>
<c>some string</c>
</X>
(essentially showing that, element 'X' can have only one of the elements 'a', 'b' or 'c' as a child element)
Lets see how the above XSD example, can be made a little different using XSD elements <attribute> and <assert>. Below is such a modified XSD document,
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:choice>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
<xs:element name="c" type="xs:string"/>
</xs:choice>
<xs:attribute name="isB" type="xs:boolean" use="required"/>
<xs:assert test="if (@isB = true()) then b else not(b)"/>
</xs:complexType>
</xs:element>
</xs:schema>
The complete meaning of above XSD document is following,
1) The <choice> with three <element> declarations below it, essentially are the same constraints as the earlier XSD document has shown.
2) This schema additionally specifies, a mandatory boolean typed attribute named 'isB'.
3) The <assert> specifies that, if value of attribute 'isB' is true then element 'b' must be present as a child of element 'X'. If value of attribute 'isB' is false, then element 'X' cannot have element 'b' as its child but one of elements 'a' or 'c' would be a valid child of element 'X'.
The following XML instance documents would be valid according to above mentioned XSD document:
<X isB="1">
<b>some string</b>
</X>
,
<X isB="0">
<a>some string</a>
</X>
,
<X isB="0">
<c>some string</c>
</X>
And, the following XML instance documents would be invalid according to the same XSD document:
<X isB="0">
<b>some string</b>
</X>
,
<X isB="1">
<a>some string</a>
</X>
,
<X isB="0">
<d>some string</d>
</X>
Now lets consider another XSD example, where the schema document specifies a choice between three or more sequences. Below is mentioned such a schema document:
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element name="a" type="xs:string"/>
<xs:element name="b" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="p" type="xs:string"/>
<xs:element name="q" type="xs:string"/>
</xs:sequence>
<xs:sequence>
<xs:element name="x" type="xs:string"/>
<xs:element name="y" type="xs:string"/>
</xs:sequence>
</xs:choice>
<xs:attribute name="isSeqTwo" type="xs:boolean" use="required"/>
<xs:assert test="if (@isSeqTwo = true()) then p else not(p)"/>
</xs:complexType>
</xs:element>
</xs:schema>
The complete meaning of above XSD document is following,
1) A <choice> is specified between three <sequence> elements. Therefore, element 'X' can have one of following sequences as its child: {a, b}, {p, q} or {x, y}.
2) This schema additionally specifies, a mandatory boolean typed attribute named 'isSeqTwo'.
3) The <assert> specifies that, if value of attribute 'isSeqTwo' is true then sequence {p, q} must be present as a child of element 'X'. If value of attribute 'isSeqTwo' is false, then element 'X' cannot have sequence {p, q} as its child but one of sequences {a, b} or {x, y} would be a valid child of element 'X'.
The following XML instance documents would be valid according to above mentioned XSD document:
<X isSeqTwo="1">
<p>string1</p>
<q>string2</q>
</X>
,
<X isSeqTwo="0">
<a>string1</a>
<b>string2</b>
</X>
,
<X isSeqTwo="0">
<x>string1</x>
<y>string2</y>
</X>
And, the following XML instance documents would be invalid according to the same XSD document:
<X isSeqTwo="0">
<p>string1</p>
<q>string2</q>
</X>
,
<X isSeqTwo="1">
<a>string1</a>
<b>string2</b>
</X>
,
<X isSeqTwo="0">
<i>string1</i>
<j>string2</j>
</X>
All the above examples, and any other XSD 1.0/1.1 constructs may be used with any standards compliant XSD validator.
That's about all I wanted to say, about this topic.
Saturday, January 25, 2020
Apache Xerces-J 2.12.1 now available
On behalf of Apache Xerces XML project team, I'm pleased to share that version 2.12.1 of Apache Xerces-J is now available. For more information about this new Xerces-J release and to download Xerces-J, please visit the Xerces-J site.
Friday, March 29, 2019
XSLT 1.0 transformations for large xml input documents
I thought that, this topic could be of interest to XML community.
I've discovered an interesting aspect of JAXP API (Java API for XML Processing) that seems to have relations to streaming that we talk with XSLT 3.0. Please see following document, and an example given in its section 4.12 (that explains JAXP's StAX API and using it with JAXP's transformation APIs)
Using the cited JAXP code in above document, one can transform very large XML input documents (I've tried an XML input document with size of about 700 MB, that worked) using XSLT 1.0 (the JDK's built in JAXP implementation can do this. I've tried with JDK 1.8 which works fine for this). It can do certain kinds of XSLT 1.0 transformations with very large XML input documents, very well. When doing the same transformations with XSLT 2.0, or with XSLT 3.0 in non streaming way, we would usually get following errors 'java.lang.OutOfMemoryError: Java heap space'.
I've written few complete examples for this topic here, https://github.com/mukulga/largexml_xslt10.
Sunday, July 29, 2018
Co-occurrence constraints and Conditional Type Assignment, with XML Schema 1.1
With respect to following article, that I wrote for XML.com : https://www.xml.com/articles/2018/05/29/co-occurrence-cta-xsd/ , I wish to add few more points to that article, via this blog post as mentioned below,
1) Using "if" control expressions in an XSD <assert>
The XPath 2.0 "if" expression is an useful facility for an <assert>. I'll explain this, via a XML schema validation example, as mentioned below.
XML Schema 1.1 document:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element name="b" type="xs:integer"/>
<xs:element name="c" type="xs:integer"/>
</xs:choice>
<xs:element name="a" type="xs:integer"/>
</xs:sequence>
<xs:attribute name="el" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="b"/>
<xs:enumeration value="c"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:assert test="if (@el = 'b') then b else c"/>
</xs:complexType>
</xs:element>
</xs:schema>
(the XSD <choice> specifies, that either element "b" should occur or the element "c" should occur. this is further controlled by an <assert> constraint, which specifies that if value of attribute "el" is 'b' then element "b" should occur, otherwise element "c" should occur for the <choice>.)
1) Using "if" control expressions in an XSD <assert>
The XPath 2.0 "if" expression is an useful facility for an <assert>. I'll explain this, via a XML schema validation example, as mentioned below.
XML Schema 1.1 document:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:complexType>
<xs:sequence>
<xs:choice>
<xs:element name="b" type="xs:integer"/>
<xs:element name="c" type="xs:integer"/>
</xs:choice>
<xs:element name="a" type="xs:integer"/>
</xs:sequence>
<xs:attribute name="el" use="required">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="b"/>
<xs:enumeration value="c"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:assert test="if (@el = 'b') then b else c"/>
</xs:complexType>
</xs:element>
</xs:schema>
(the XSD <choice> specifies, that either element "b" should occur or the element "c" should occur. this is further controlled by an <assert> constraint, which specifies that if value of attribute "el" is 'b' then element "b" should occur, otherwise element "c" should occur for the <choice>.)
Below are few XML instance documents, that can be validated with the above XSD document:
<X el="b">
<b>100</b>
<a>200</a>
</X>
(valid document)
<X el="b">
<c>100</c>
<a>200</a>
</X>
(invalid document, since the preceding-sibling of element "a" must be element "b")
<X el="p">
<b>100</b>
<a>200</a>
</X>
(invalid document, since the value of attribute "el" is not as per the simpleType definition of attribute "el". the <assert> would also fail.)
2) Using XSD <alternative> instead of <assert>
The XSD example mentioned in point 1) above, can easily be converted to an XSD document using <alternative> to solve the same use case. Below is a modified XSD 1.1 document, using <alternative> element solving the same use case as mentioned in point 1) above.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="X">
<xs:alternative test="@el = 'b'" type="B_type"/>
<xs:alternative test="@el = 'c'" type="C_type"/>
<xs:alternative type="xs:error"/>
</xs:element>
<xs:complexType name="B_type">
<xs:sequence>
<xs:element name="b" type="xs:integer"/>
<xs:element name="a" type="xs:integer"/>
</xs:sequence>
<xs:attribute name="el" type="xs:string" use="required"/>
</xs:complexType>
<xs:complexType name="C_type">
<xs:sequence>
<xs:element name="c" type="xs:integer"/>
<xs:element name="a" type="xs:integer"/>
</xs:sequence>
<xs:attribute name="el" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
Subscribe to:
Posts (Atom)