Search code examples
xmlxsdxsd-validationxml-validation

XSD optional vs required for child elements based on attribute value?


I have an xml structure like this. I want to make a schema (XSD) validation which makes the <DataRequest> node with Name attribute values <Bob> and <Rob> optional:

 <Request>
     <DataRequest Name="Bob"></DataRequest>
     <DataRequest Name="Rob"></DataRequest>  
     <DataRequest Name="Smith"></DataRequest>  
     <DataRequest Name="Andy"></DataRequest>  
 </Request>

I have done validation for the possible Name attribute values, but I am unable to make some values optional:

<xs:element maxOccurs="unbounded" name="DataRequest" >
  <xs:complexType>
    <xs:attribute name="Name"  use="required">
      <xs:simpleType>
        <xs:restriction base="xs:string">
          <xs:enumeration value="Bob" />
          <xs:enumeration value="Rob"/>
          <xs:enumeration value="Andy"/>
          <xs:enumeration value="Smith/>
        </xs:restriction>
      </xs:simpleType>
   </xs:attribute>
  </xs:complexType>
</xs:element>

Solution

  • XSD 1.0

    Optionality cannot depend upon an attribute value in XSD 1.0, but if you redesign your XML,

    <Request>
        <Bob></Bob>
        <Rob></Rob>  
        <Smith></Smith>  
        <Andy></Andy>  
    </Request>
    

    you could trivially use minOccurs="0" in to specify that Bob and Rob may be omitted:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               version="1.0">
      <xs:element name="Request">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="Bob" minOccurs="0"/>
            <xs:element name="Rob" minOccurs="0"/>
            <xs:element name="Smith"/>
            <xs:element name="Andy"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:schema>
    

    XSD 1.1

    You can use xs:assert to specify optionality/requiredness based upon an attribute value.

    Here, we assert that the other enumerations, are required, leaving Bob and Rob optional:

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning" 
               elementFormDefault="qualified"
               vc:minVersion="1.1">
      <xs:element name="Request">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="DataRequest" maxOccurs="unbounded">
              <xs:complexType>
                <xs:attribute name="Name" use="required">
                  <xs:simpleType>
                    <xs:restriction base="xs:string">
                      <xs:enumeration value="Bob"/>
                      <xs:enumeration value="Rob"/>
                      <xs:enumeration value="Andy"/>
                      <xs:enumeration value="Smith"/>
                    </xs:restriction>
                  </xs:simpleType>
                </xs:attribute>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
          <xs:assert test="DataRequest[@Name='Smith']"/>
          <xs:assert test="DataRequest[@Name='Andy']"/>
        </xs:complexType>
      </xs:element>
    </xs:schema>