3

I am trying to write an assertion that will make the values of @row and @column less than or equal to the values of @rows and @columns in the parent element <structure>.

<xs:element name="structure">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="cell" maxOccurs="unbounded">
                <xs:complexType>
                    <xs:attribute name="row" type="xs:positiveInteger"/>   
                    <xs:attribute name="column" type="xs:positiveInteger"/>
                    <xs:assert test="@row le @rows"/>
                    <xs:assert test="@column le @columns"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="rows" type="xs:positiveInteger" use="optional"/>
        <xs:attribute name="columns" type="xs:positiveInteger" use="optional"/>
    </xs:complexType>
</xs:element>

Are my assertions in the wrong place? What XPath expression do I use to specify the parent node? My editor isn't letting me write ..@rows.

kjhughes
  • 106,133
  • 27
  • 181
  • 240
Misenus
  • 139
  • 10
  • how about `../@rows`? – har07 May 12 '16 at 03:02
  • Didn't work. I tried a value of 21 for `@rows` and a value of 1 for `@row` and got this error message: Description: cvc-assertion: Assertion evaluation ('@row le ../@rows') for element 'cell' on schema type '#AnonType_cellstructurebodypuzzle' did not succeed. – Misenus May 12 '16 at 03:10
  • 2
    @har07: That seems logical from an XPath perspective, but XSD assertions cannot access nodes outside the scope of the governing element. [Solution](http://stackoverflow.com/a/37176621/290085) is to move assertions up to highest context over which constraints are to be expressed. – kjhughes May 12 '16 at 03:14

1 Answers1

4

An assertion XPath cannot reach outside of its context.

So, move your assertion up to the structure element, and use an every ... satisfies assertion test:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           elementFormDefault="qualified"
           vc:minVersion="1.1">
    <xs:element name="structure">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="cell" maxOccurs="unbounded">
                    <xs:complexType>
                        <xs:attribute name="row" type="xs:positiveInteger"/>   
                        <xs:attribute name="column" type="xs:positiveInteger"/>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="rows" type="xs:positiveInteger" use="optional"/>
            <xs:attribute name="columns" type="xs:positiveInteger" use="optional"/>
            <xs:assert test="every $r in cell/@row satisfies @rows >= $r"/>
            <xs:assert test="every $c in cell/@column satisfies @columns >= $c"/>
        </xs:complexType>
    </xs:element>
</xs:schema>
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • Incidentally, the Saxon XSD 1.1 processor recognizes assertions in the form "every X satisfies T" and treats them specially, in that the diagnostics will tell you which X failed to satisfy T. – Michael Kay May 12 '16 at 07:42
  • @MichaelKay, nice touch -- much more helpful than just a blanket pass/fail. – kjhughes May 12 '16 at 14:19