Search code examples
xsdassert

XSD 1.1 Assert to Count and Compare Elements


I currently have an XSD file which controls the validation etc towards my corresponding XML file, and I would like to control (preferably using an assert command rather than XLST [as I have no prior knowledge of this]) and be able to ensure there are the same number of abc:Country tags to abc:AccountNumber tags, as one should correspond to the other

    <abc:Account>
      <abc:Individual>
        <abc:Country>Germany</abc:Country>
        <abc:Country>Australia</abc:Country>
        <abs:AccountNumber issuedBy="DE">123456</abs:AccountNumber>
        <abs:AccountNumber issuedBy="AU">654321</abs:AccountNumber>
      </abc:Individual>
    </abc:Account>

Please can someone help me out with the assert command I can use perform this validation?

I have tried the following to no avail...

    <xsd:assert test="if (count (abc:Account/abc:Individual/abc:Country) eq (count (abc:Account/abc:Individual/AccountNumber))) then true() else false() "/>

or this....

    <xsd:assert test="count (abc:Account/abc:Individual/abc:Country) eq count (abc:Account/abc:Individual/AccountNumber)"/>

I presume this is doable using XSD 1.1?

any help will be greatly appreciated.... thanks


Solution

  • I think it makes most sense to have the assert in the type definition for the abc:Individual element, then the assert is simply:

    count(abc:Country) eq count(abc:AccountNumber)
    

    The complete schema is like so. For simplicity I kept AccountNumber in the abc namespace, but it can be easily replaced with a reference otherwise.

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:abc="http://www.example.com/abc"
        targetNamespace="http://www.example.com/abc"
        xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
        vc:minVersion="1.1">
        <xs:element name="Account">
            <xs:complexType>
                <xs:sequence>
                    <xs:element ref="abc:Individual" maxOccurs="unbounded" />
                </xs:sequence>
            </xs:complexType>
        </xs:element>
        <xs:element name="Individual">
            <xs:complexType>
                <xs:sequence>
                    <xs:element ref="abc:Country" maxOccurs="unbounded" />
                    <xs:element ref="abc:AccountNumber" maxOccurs="unbounded" />
                </xs:sequence>
                <xs:assert test="count(abc:Country) eq count(abc:AccountNumber)"/>
            </xs:complexType>
        </xs:element>
        <xs:element name="Country" type="xs:string"/>
        <xs:element name="AccountNumber">
            <xs:complexType>
                <xs:simpleContent>
                    <xs:extension base="xs:string">
                        <xs:attribute name="issuedBy" type="xs:string"/>
                    </xs:extension>
                </xs:simpleContent>
            </xs:complexType>
        </xs:element>
    </xs:schema>
    

    Apart from changing abs to abc, the original document validates successfully against the schema, i.e.:

    <?xml version="1.0" encoding="UTF-8"?>
    <abc:Account
        xmlns:abc="http://www.example.com/abc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.example.com/abc test.xsd">
        <abc:Individual>
            <abc:Country>Germany</abc:Country>
            <abc:Country>Australia</abc:Country>
            <abc:AccountNumber issuedBy="DE">123456</abc:AccountNumber>
            <abc:AccountNumber issuedBy="AU">654321</abc:AccountNumber>
        </abc:Individual>
    </abc:Account>