Question

Here's what I got:

<xs:element name="items">
  <xs:complexType>
    <xs:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
  </xs:complexType>
</xs:element>

<xs:element name="item">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="id"/>
      <xs:element ref="filename"/>
            <xs:element ref="file_url"/>
      <xs:element ref="metadata"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

Now I want metadata to be optional, but the following should be invalid:

<items>
  <item>
    <id>1</id>
    <filename>asd.dat</filename>
    <file_url>bla</file_url>
    <metadata>...</metadata>
  </item>
  <item>
    <id>1</id>
    <filename>asd.dat</filename>
    <file_url>bla</file_url>
    <!-- metadata missing -->
  </item>
</items>

So either it should be missing everywhere, or be present everywhere. How do I do this?

Was it helpful?

Solution

XSD 1.0

You cannot directly represent your constraint in XML Schema 1.0. You could use Schematron or check it at the application level. You could also rewrite your XSD to allow two types of items: item which does not allow metadata and item_meta which requires it:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="items">
    <xs:complexType>
      <xs:choice>
        <xs:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
        <xs:element ref="item_meta" minOccurs="0" maxOccurs="unbounded"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <xs:group name="commonItemElements">
    <xs:sequence>
      <xs:element name="id"/>
      <xs:element name="filename"/>
      <xs:element name="file_url"/>
    </xs:sequence>
  </xs:group>
  <xs:element name="item">
    <xs:complexType>
      <xs:group ref="commonItemElements"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="item_meta">
    <xs:complexType>
      <xs:sequence>
        <xs:group ref="commonItemElements"/>
        <xs:element name="metadata"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSD 1.1

In XML Schema 1.1, you can specify co-occurrence constraints via XPath 2.0 using xs:assert to constrain the number of optional metadata elements to be 0 or equal to the number of item elements:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="items">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="item" minOccurs="0" maxOccurs="unbounded"/>
      </xs:sequence>
      <xs:assert test="(count(item/metadata) = 0) or (count(item/metadata) = count(item))"/>
    </xs:complexType>
  </xs:element>
  <xs:element name="item">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="id"/>
        <xs:element name="filename"/>
        <xs:element name="file_url"/>
        <xs:element name="metadata" minOccurs="0"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top