Search code examples
xmlxsd-1.1xsd-1.0xmlschema

XSD data type of child element depending on parent element's attribute


I have some reports which look like this:

<report>
  <dataset datatype="integer">
     <data timestamp="1970-01-01T00:00:00+01:00">25</data>
     <data timestamp="1970-01-01T00:01:00+01:00">25</data>
     <data timestamp="1970-01-01T00:02:00+01:00">25</data>
     <data timestamp="1970-01-01T00:03:00+01:00">25</data>
  </dataset>
  <dataset datatype="string">
     <data timestamp="1970-01-01T00:00:00+01:00">foo</data>
     <data timestamp="1970-01-01T00:01:00+01:00">bar</data>
     <data timestamp="1970-01-01T00:02:00+01:00">baz</data>
     <data timestamp="1970-01-01T00:03:00+01:00">foobar</data>
  </dataset>
</report>

I need a xml schema definition describing the XML above. So far no problem. The issue I couldn't solve is how to do is the following: The type of the data elements needs to depend on the datatype attribute of the data set element.

Datatype could be: string, float or integer. E.g. the datatype attribute is set to "integer" all child "data" elements should be restricted to the type "xs:integer".

Here is my XSD except for the type restriction:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:simpleType name="DataTypes">
        <xs:restriction base="xs:string">
            <xs:enumeration value="string"/>
            <xs:enumeration value="integer"/>
            <xs:enumeration value="float"/>
        </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="Data">
        <xs:simpleContent>
            <xs:extension base="xs:anySimpleType">
                <xs:attribute name="timestamp" type="xs:dateTime" use="required" />
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="Dataset">
        <xs:sequence>
            <xs:element name="data" type="Data" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="datatype" type="DataTypes" use="required" />
    </xs:complexType>

    <xs:element name="report">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="dataset" type="Dataset" minOccurs="1" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

I am grateful for every helpful idea!


Solution

  • The type of the data elements needs to depend on the datatype attribute of the data set element.

    That's a very precise description of the "conditional type attribution" feature that was added to XSD 1.1. It's also known as "type alternatives". Be aware that not all XSD processors support XSD 1.1.

    You can find some examples at XSD 1.1 xs:alternative/xs:assert

    This can't be done in XSD 1.0.