XSD schema validation – how to deal with a repeating group that also contains elements that can appear in any order?

Below is the XML that I need to validate. <Trustee> node is a repeating group and <TrustNameOptions> element can appear in any order, before or after <Trustee>
<Trust>
    <ABN>123456</ABN>
    <TrustName>Trust name</TrustName>
    <TrustNameOptions/>
    <Trustee>
        <TrusteeType>Individual</TrusteeType>
        <IndividualTrustee>
            <FirstName>John</FirstName>
        </IndividualTrustee>
    </Trustee>
    <Trustee>
        <TrusteeType>Company</TrusteeType>
        <CompanyTrustee>
            <Name>Company name</Name>
        </CompanyTrustee>
    </Trustee>
</Trust>
So how do I validate the XML? <xsd:all> allows elements to appear in any order, but it only allows maxOccurs=”1″ for <Trustee> (not “unbounded” which it needs to be).
<!-- Doesn't work -->
<xsd:element name="Trust">
  <xsd:complexType>
      <xsd:all>
          <xsd:element name="ABN" type="abn"/>
          <xsd:element name="TrustName" type="entityNameSafeString"/>
          <xsd:element name="TrustNameOptions" type="entityNameSafeString" minOccurs="0"/>
          <xsd:element name="Trustee" type="trusteeType" minOccurs="0" maxOccurs="1"/>
      </xsd:all>
  </xsd:complexType>
</xsd:element>
Using <xsd:sequence> allows maxOccurs=”unbounded” for <Trustee> but it means the elements have to appear in sequence (defined order), so having <TrustNameOptions> appear in any order doesn’t work.
<!-- Doesn't work -->
<xsd:element name="Trust">
  <xsd:complexType>
      <xsd:sequence>
          <xsd:element name="ABN" type="abn"/>
          <xsd:element name="TrustName" type="entityNameSafeString"/>
          <xsd:element name="TrustNameOptions" type="entityNameSafeString" minOccurs="0"/>
          <xsd:element name="Trustee" type="trusteeType" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
  </xsd:complexType>
</xsd:element>
Solution = use <xsd:choice maxOccurs=”unbounded”>. This worked, it allowed me to combine my requirements. Allows elements to appear in any order and to also have a repeating group <Trustee> (maxOccurs=”unbounded”). I found this solution on stack overflow
<!-- Works -->
<xsd:element name="Trust">
  <xsd:complexType>
      <xsd:choice maxOccurs="unbounded">
          <xsd:element name="ABN" type="abn"/>
          <xsd:element name="TrustName" type="entityNameSafeString"/>
          <xsd:element name="TrustNameOptions" type="entityNameSafeString" minOccurs="0"/>
          <xsd:element name="Trustee" type="trusteeType" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:choice>
  </xsd:complexType>
</xsd:element>
However, my team wasn’t very comfortable with this solution. We decided to try and make <TrustNameOptions> appear in order (above <Trustee>). Then we could simply use <xsd:sequence> like normal. Failing this, we decided it was maybe ok to use <xsd:choice> as long as our downstream system which used XJC (XML schema binding to Java classes) worked, and could handle the <xsd:choice maxOccurs=”unbounded”>. I ended up getting things to appear in order, so we went with <xsd:sequence>

Leave a Reply

Your email address will not be published. Required fields are marked *