Search code examples
xmlxsdxmllint

Assertion contains for XSD


I want to create a conditional validation for XML with a XSD. I want if the element Unit is "uri" then the element Value must contains "http", else if element Unit is "date" then the element Value must be a timestamp, and so on... I am starting with a simple validation using xs:assert and is not working. I already tested xs:assertion but it produced the same error.

xmllint --noout --schema metadata.xsd metadata.xml 
metadata.xsd:46: element assert: Schemas parser error : Element '{http://www.w3.org/2001/XMLSchema}complexType': The content is not valid. Expected is (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))).
WXS schema metadata.xsd failed to compile

.

<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="metadata">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="AVU" minOccurs="0" maxOccurs="unbounded">
     <xs:complexType>
      <xs:sequence>

       <xs:element name="Target" minOccurs="0">
        <xs:simpleType>
         <xs:restriction base="xs:string">
          <xs:maxLength value="1088"/>
         </xs:restriction>
        </xs:simpleType>
       </xs:element>

       <xs:element name="Attribute">
        <xs:simpleType>
         <xs:restriction base="xs:string">
          <xs:minLength value="1"/>
          <xs:maxLength value="2700"/>
         </xs:restriction>
        </xs:simpleType>
       </xs:element>

       <xs:element name="Value">
        <xs:simpleType>
         <xs:restriction base="xs:string">
          <xs:pattern value="http://.*"/>
          <xs:maxLength value="2700"/>
         </xs:restriction>
        </xs:simpleType>
       </xs:element>

       <xs:element name="Unit">
        <xs:simpleType>
         <xs:restriction base="xs:string">
          <xs:pattern value="uri|string|integer|date|float"/>
          <xs:maxLength value="250"/>
         </xs:restriction>
        </xs:simpleType>
       </xs:element>

      </xs:sequence>
      <xs:assert test="Unit = 'uri'" />
     </xs:complexType>
    </xs:element>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Solution

  • As @potame and @MichaelKay have already said, your error is due to using xs:assert with XSD 1.0 processor when xs:assert requires an XSD 1.1 processor.

    You have a few options:

    1. Accept less stringent validation.
    2. Validate outside of XSD.
    3. Switch to an XSD 1.1 processor.
    4. Redesign your XML.

    Regarding #4, your XML is highly abstract right now. If you were to move toward more concrete element naming, XSD 1.0 could do more type checking for you. For example, instead of a Unit element requiring special checking of an Value element when Unit is uri, you could simply have a URI element of type xsd:anyURI. (In fact, you might be even more concrete and name URI for what it is rather than for its type; for example: Homepage or PaymentAPIEndpoint.)