CasaDelGato
CasaDelGato

Reputation: 645

xs:assert always fails with xerces validation, but works in xmlspy

I'm setting up Schema for our xml input/output, and have run into an issue where XMLSpy validates ok, but Xerces fails on one of the xs:asserts. I'm using the latest xerces, xerces-2_12_0-xml-schema-1.1.

I have included all the .jar files from that distribution (except the xercesSamples.jar)

The test code is:

SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/XML/XMLSchema/v1.1");
factory.setFeature("http://apache.org/xml/features/validation/cta-full-xpath-checking", true);
Schema schema = factory.newSchema(new File("C:/Imports/Test.xsd"));
validator = schema.newValidator();
validator.validate(new StreamSource("C:/Imports/Test.xml"));

I've trimmed the xsd file down to this:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:lit="http://www.w3schools.com" xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" targetNamespace="http://www.w3schools.com" elementFormDefault="qualified" attributeFormDefault="unqualified" vc:minVersion="1.1">
    <xs:element name="MetrixXML">
        <xs:complexType>
            <xs:all>
                <xs:element ref="lit:Page" minOccurs="1" maxOccurs="unbounded"/>
            </xs:all>
            <xs:attribute name="SchemaVersion" type="xs:float" use="required"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="Page">
        <xs:complexType>
            <xs:attribute name="ContentPositionRule" type="xs:string"/>
            <xs:attribute name="FilePageNum" type="xs:nonNegativeInteger"/>
            <xs:assert test="(//@SchemaVersion ge 2.1) or ((//@SchemaVersion lt 2.1) and not (@ContentPositionRule))"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

The xml is:

<?xml version="1.0" encoding="UTF-8"?>
<MetrixXML xmlns="http://www.w3schools.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com Test.xsd" SchemaVersion="2.1" >
    <Page FilePageNum="1"/>
    <Page ContentPositionRule="CenterEachPage"/>
</MetrixXML>

The error I get is:

org.xml.sax.SAXParseException: cvc-assertion: Assertion evaluation ('(//@SchemaVersion ge 2.1) or ((//@SchemaVersion lt 2.1) and not (@ContentPositionRule))') for element 'Page' on schema type '#AnonType_Page' did not succeed.

In XMLSpy, if I set SchemaVersion to 2.0, the assert fails. If I set it to 2.1, the assert succeeds.

Is there some Feature flag that I need to set?

Update: Apparently XMLSpy is allowing things it shouldn't allow.

So, the desired test is that if (SchemaVersion < 2.1) AND any element contains a "ContentPositionRule" attribute THEN it should fail.

Upvotes: 1

Views: 739

Answers (1)

kjhughes
kjhughes

Reputation: 111561

Move the assertion up a level in the hierarchy and ensure that it references only descendents of the associated element:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:lit="http://www.w3schools.com"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           targetNamespace="http://www.w3schools.com" 
           elementFormDefault="qualified"
           attributeFormDefault="unqualified" vc:minVersion="1.1">
  <xs:element name="MetrixXML">
    <xs:complexType>
      <xs:all>
        <xs:element ref="lit:Page" minOccurs="1" maxOccurs="unbounded"/>
      </xs:all>
      <xs:attribute name="SchemaVersion" type="xs:float" use="required"/>
      <xs:assert test=" (@SchemaVersion ge 2.1) or 
                       ((@SchemaVersion lt 2.1) and 
                         not (lit:Page/@ContentPositionRule))       
</xs:complexType>
  </xs:element>
  <xs:element name="Page">
    <xs:complexType>
      <xs:attribute name="ContentPositionRule" type="xs:string"/>
      <xs:attribute name="FilePageNum" type="xs:nonNegativeInteger"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

An assertion is only allowed to reference the element on which it appears and that element's descendents – not its ancestors, siblings, etc.

See also:

XMLSpy's observed behavior

Although it's technically (albeit unhelpfully) conformant to provide no diagnostic assistance for assertions over siblings or ancestors of the element on which an assertion appears, XMLSpy should not be reporting differing validation results depending upon sibling or ancestor state.

W3C XML Schema Definition Language (XSD) 1.1 Part 1: Structures

Validation Rule: Assertion Satisfied

[...]

1.3 From the "partial" ·post-schema-validation infoset·, a data model instance is constructed as described in [XDM]. The root node of the [XDM] instance is constructed from E; the data model instance contains only that node and nodes constructed from the [attributes], [children], and descendants of E. Note: It is a consequence of this construction that attempts to refer, in an assertion, to the siblings or ancestors of E, or to any part of the input document outside of E itself, will be unsuccessful. Such attempted references are not in themselves errors, but the data model instance used to evaluate them does not include any representation of any parts of the document outside of E, so they cannot be referred to.

Note: It is a consequence of this construction that attempts to refer, in an assertion, to the siblings or ancestors of E, or to any part of the input document outside of E itself, will be unsuccessful. Such attempted references are not in themselves errors, but the data model instance used to evaluate them does not include any representation of any parts of the document outside of E, so they cannot be referred to.

[Emphasis added.]

Upvotes: 1

Related Questions