Friday, October 28, 2016

XML Schema 1.1 : assertion refines enumeration

In this post, I'll try to explain how the XML Schema 1.1 <assertion> facet refines the XML Schema <enumeration> facet in useful ways, and also helps us build a useful domain vocabulary written in the XML Schema language.

Consider the following 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="day" type="Day"/>
  
   <xs:element name="workday" type="WorkDay"/>
  
   <xs:element name="holiday" type="Holiday"/>
  
   <xs:simpleType name="WorkDay">
      <xs:restriction base="Day">
         <xs:assertion test="$value != 'saturday' and $value != 'sunday'"/>
      </xs:restriction>
   </xs:simpleType>
  
   <xs:simpleType name="Holiday">
     <xs:restriction base="Day">
        <xs:assertion test="$value = 'saturday' or $value = 'sunday'"/>
     </xs:restriction>
   </xs:simpleType> 
  
   <xs:simpleType name="Day">
      <xs:restriction base="xs:string">
         <xs:enumeration value="monday"/>
         <xs:enumeration value="tuesday"/>
         <xs:enumeration value="wednesday"/>
         <xs:enumeration value="thursday"/>
         <xs:enumeration value="friday"/>
         <xs:enumeration value="saturday"/>
         <xs:enumeration value="sunday"/>
      </xs:restriction>
   </xs:simpleType>
 
</xs:schema>

This is a very simple XSD document, and the XML documents validated by this XSD document will also be very simple.

The following is one invalid document for the given schema,
<holiday>wednesday</holiday>

To my opinion, this example has illustrated how the <assertion> facet refines the <enumeration> facet during simple type derivation, and also helps us clearly build a fine domain vocabulary. The types "WorkDay" and "Holiday" are verbally linked to the type "Day" in the XML Schema document as in this example.

Monday, October 3, 2016

XML Schema 1.1 : overlap in concept of CTA and "assert"

Here's another example, where I thought Conditional Type Alternative would have worked. It cannot in this case, because we have an attribute on element "X" and the data type is simple. Therefore we have to use an <assert> to solve this (because there's lot of conditional stuff here, an use case of XPath 2.0 "if", and a straight forward case of co-occurrence constraints).

Two valid XMLs:

(for attribute value 1, the simple type content of element "X" must be even)
<?xml version="1.0" encoding="UTF-8"?>
<X xa="1">
   4
</X>

(for attribute value 2, the simple type content of element "X" must be odd)
<?xml version="1.0" encoding="UTF-8"?>
<X xa="2">
   5
</X>

Invalid XML (attribute value other than 1 or 2 is not allowed):
<?xml version="1.0" encoding="UTF-8"?>
<X xa="3">
   4
</X>

The XML Schema 1.1 solution is below:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

   <xs:element name="X">
      <xs:complexType>
         <xs:simpleContent>
            <xs:extension base="xs:int">
               <xs:attribute name="xa" type="xs:int"/>
               <xs:assert test="if (@xa = 1) then $value mod 2 = 0
                            else if (@xa = 2) then $value mod 2 = 1
                                else false()"/>
            </xs:extension>
         </xs:simpleContent>
      </xs:complexType>
   </xs:element>
 
</xs:schema>

I hope this example is helpful.