Saturday, September 24, 2016

XML Schema 1.1 assertion facet on a simple type list and union

Here's some more information I have on using an XML Schema 1.1 <assertion> facet, when a simple type is used that has variety list or union. Note that, an XSD simple type can be of following 3 kinds:

1) <xs:simpleType
        <xs:restrition base="some-type

2) <xs:simpleType
       <xs:list itemType="some-type

3) <xs:simpleType
       <xs:union memberTypes="type-1, type-2, ..."


Example of an XML Schema simple type with variety list:
XML document:
<?xml version="1.0" encoding="UTF-8"?>
<X>1 2 3 4 5</X>

Write an XML Schema 1.1 document, that will report an XML document as valid when following conditions are met:
The element "X" has a simple type with variety list, such that the item type of the list is a simple type that validates even numbers.

The following XML Schema 1.1 document, is the solution for this requirement:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

   <xs:element name="X">
        <xs:simpleType>
            <xs:list itemType="EvenNum"/>
        </xs:simpleType>
   </xs:element>
  
   <xs:simpleType name="EvenNum">
        <xs:restriction base="xs:int">
            <xs:assertion test="$value mod 2 = 0"/>
        </xs:restriction>
   </xs:simpleType>
 
</xs:schema>

In this example, the XML document has following values as invalid in the list: 1, 3 & 5. When validated with Apache Xerces, following XML Schema validation outcome is reported:

[Error] list.xml:2:17: cvc-assertions-valid: Value '1' is not facet-valid with respect to assertion '$value mod 2 = 0'.
[Error] list.xml:2:17: cvc-assertion: Assertion evaluation ('$value mod 2 = 0') for element 'X' on schema type 'EvenNum' did not succeed. Assertion failed for an xs:list member value '1'.
[Error] list.xml:2:17: cvc-assertions-valid: Value '3' is not facet-valid with respect to assertion '$value mod 2 = 0'.
[Error] list.xml:2:17: cvc-assertion: Assertion evaluation ('$value mod 2 = 0') for element 'X' on schema type 'EvenNum' did not succeed. Assertion failed for an xs:list member value '3'.
[Error] list.xml:2:17: cvc-assertions-valid: Value '5' is not facet-valid with respect to assertion '$value mod 2 = 0'.
[Error] list.xml:2:17: cvc-assertion: Assertion evaluation ('$value mod 2 = 0') for element 'X' on schema type 'EvenNum' did not succeed. Assertion failed for an xs:list member value '5'.

A valid XML document will be, for example: <X>2 4</X>.

Example of an XML Schema simple type with variety union (its called union, because the value space of the simple type is a union of 2 or more simple types):
XML document:
<?xml version="1.0" encoding="UTF-8"?>
<X>
    <val>3</val>
    <val>2017-12-05</val>
</X>

Write an XML Schema 1.1 document, that will report an XML document as valid when following conditions are met:
The element "X" has an XSD complex type with following description,
Its a sequence of "val" elements (let's say maxOccurs of it is 5, or it could be unbounded if you wish). The value of element "val" is defined by the following simple type,
Its an union of 2 simple types T1 and T2 with following definitions:

<!-- a simple type validating even numbers -->
<xs:simpleType name="T1">
        <xs:restriction base="xs:int">
            <xs:assertion test="$value mod 2 = 0"/>
        </xs:restriction>
</xs:simpleType>  

<!-- a simple type that validates specific date values; values that are less than a specific date -->
<xs:simpleType name="T2">
      <xs:restriction base="xs:date">
          <xs:assertion test="$value lt xs:date('2016-01-01')"/>
      </xs:restriction>
</xs:simpleType>

The following XML Schema 1.1 document is a complete schema document, that is a solution for this requirement:

<?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:element name="val" maxOccurs="5">
                  <xs:simpleType>
                      <xs:union memberTypes="T1 T2"/>
                  </xs:simpleType>
               </xs:element>
            </xs:sequence>
        </xs:complexType>
   </xs:element>
  
   <xs:simpleType name="T1">
        <xs:restriction base="xs:int">
            <xs:assertion test="$value mod 2 = 0"/>
        </xs:restriction>
   </xs:simpleType>
  
   <xs:simpleType name="T2">
        <xs:restriction base="xs:date">
            <xs:assertion test="$value lt xs:date('2016-01-01')"/>
        </xs:restriction>
   </xs:simpleType>
 
</xs:schema>

For the XML document given (an invalid one), the following validation outcomes are reported by Apache Xerces's XML Schema 1.1 validator:

[Error] union.xml:3:15: cvc-assertions-valid-union-elem: Value '3' is not facet-valid with respect to the specified assertions, on type '#AnonType_valX' on element 'val'.
[Error] union.xml:3:15: cvc-datatype-valid.1.2.3: '3' is not a valid value of union type '#AnonType_valX'.
[Error] union.xml:3:15: cvc-type.3.1.3: The value '3' of element 'val' is not valid.
[Error] union.xml:4:24: cvc-assertions-valid-union-elem: Value '2017-12-05' is not facet-valid with respect to the specified assertions, on type '#AnonType_valX' on element 'val'.
[Error] union.xml:4:24: cvc-datatype-valid.1.2.3: '2017-12-05' is not a valid value of union type '#AnonType_valX'.
[Error] union.xml:4:24: cvc-type.3.1.3: The value '2017-12-05' of element 'val' is not valid.

It should be fairly easy, to specify one of a valid XML documents for this requirement.

No comments: