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>