Search code examples
xmlxsdxsd-validationxsd-1.1xmlschema

XSD 1.1: Assert if value of attribute is contained in enum


I have element Config, which contains 3 attributes: device, name and value.

    <Config device="phone" name="id" value="1111" />

Based on @name's value I want to validate attribute @value to be string, int or boolean. I created schema using xs:alternative that allows to change type of element based on attributes.

<xs:element name="Config" type="configType">
    <xs:alternative type="configInt" test="@name = ('id','port')" />
    <xs:alternative type="configString" test="@name = ('deviceUdid','company')" />
    <xs:alternative type="configBoolean" test="@name = ('isRunning','isStopped')" />
</xs:element>
<!-- Base for Config -->
<xs:complexType name="configType">
    <xs:attribute name="device" type="devices" />
</xs:complexType>

<!-- Alternative for int -->
<xs:complexType name="configInt">
    <xs:complexContent>
        <xs:extension base="configType">
            <xs:attribute name="name" type="configIntList" />
            <xs:attribute name="value" type="xs:int" />
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<!-- Alternative for string-->
<xs:complexType name="configString">
    <xs:complexContent>
        <xs:extension base="configType">
            <xs:attribute name="name" type="configStringList" />
            <xs:attribute name="value" type="xs:string" />
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<!-- Alternative for boolean -->
<xs:complexType name="configBoolean">
    <xs:complexContent>
        <xs:extension base="configType">
            <xs:attribute name="name" type="configBooleanList" />
            <xs:attribute name="value" type="xs:boolean" />
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

For each config: configBoolean, configInt and configString I have enum of possible values for attribute "name".

<xs:simpleType name="configStringList">
  <xs:restriction base="xs:string">
    <xs:enumeration value="deviceUdid" />
    <xs:enumeration value="company" />
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="configIntList">
  <xs:restriction base="xs:string">
    <xs:enumeration value="id" />
    <xs:enumeration value="port" />
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="configBooleanList">
  <xs:restriction base="xs:string">
    <xs:enumeration value="isRunning" />
    <xs:enumeration value="isStopped" />
  </xs:restriction>
</xs:simpleType>

My question is - Am I able to use this enum for tests in xs:alternative instead of listing all possible values for @name attribute? I want to accomplish something like that:

<xs:element name="Config" type="configType">
        <xs:alternative type="configInt" test="@name = configIntList" />
        <xs:alternative type="configString" test="@name = configStringList" />
        <xs:alternative type="configBoolean" test="@name = configBooleanList" />
</xs:element>

Solution

  • While XPath 2 and later allows expressions/checks like @name castable as ns1:configIntList, i.e. allow you to check whether the value of e.g. the name attribute can be cast to a certain type like for instance the configIntList type, I don't think that will help for your use case; it seems the XPath 2 subset allow for checks of type alternatives is pretty restricted and only allows the use of built-in types, so you don't have access to types from the schema being processed.