Search code examples
xmlxpathxsd-validationxsd-1.1

XSD 1.1 Conditional Type Assignment <alternative test=""> to check if an element hasn't an attribute set?


I would like to ask if someone knows how to make an XSD 1.1 Conditional Type Assignment check if an element hasn't an attribute using the XPath query, e.g.:

<!--inline alternative type definitions --> 
<element name="TimeTravel" type="TravelType"> 
      <alternative test="@direction='Future'"> 
          <complexType> 
              <complexContent> 
              <restriction base="TravelType" 
                         .... 
<!--        some past travel related elements go here --> 
            </complexType> 
       </alternative> 
      <alternative test="@direction='Past'"> 
          <complexType> 
              <complexContent> 
              <restriction base="TravelType" 
                         .... 
   <!--        some future travel related elements go here --> 
            </complexType> 
       </alternative> 
  </element> 
                          OR 
<!--Named alternative type definitions --> 
<element name="TimeTravel" type="TravelType"> 
   <alternative test="@direction='Future' type="FutureTravelType"/> 
   <alternative test="@direction='Past' type="PastTravelType"/> 
</element>

In this example the 'alternative test=""' checks whether the attribute "direction" of the TimeTravel element has a value of "Future" or "Past". How should I write the XPath query to check if e.g. there's no "direction" attribute for the current element?


Solution

  • The XPath "@direction" will test for the presence of a direction attribute on the current element:

    <alternative test="@direction" type="DirectionType"/>
    

    The XPath "not(@direction)" will test for the absence of a direction attribute on the current element:

    <alternative test="not(@direction)" type="NoDirectionType"/>
    

    Note also that the alternative/@test attribute can be omitted altogether to provide a default type.

    <alternative type="DefaultType"/>
    

    Update to address CTA subset mode per OP's follow-up question

    So this <alternative test="@direction='a_value' and not(@another_attribute)"/> is correct and would make it right?

    Yes, but be aware that your XSD processor may use the XPath CTA (Conditional Type Assignment) subset by default. (Xerces, and therefore most Xerces-based tools, do this, for example.) If this is the case, you will get an error that looks something like this:

    c-cta-xpath: The XPath expression 'not(@direction)' couldn't compile successfully in 'cta-subset' mode, during CTA evaluation.

    c-cta-xpath: The XPath expression '@direction='a_value' and not(@another_attribute)' couldn't compile successfully in 'cta-subset' mode, during CTA evaluation.

    To use full XPath 2.0 rather than the CTA subset, configure your tool accordingly. For example, for Xerces, set the following feature to 'true':

    http://apache.org/xml/features/validation/cta-full-xpath-checking
    

    In oXygen, there's a checkbox in Options > Preferences > XML > XML Parser > XML Schema that will control the value of the feature for you.

    Using full XPath 2.0, yes, you can use and in the manner you suggest in your comment.