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>.)

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>