0

I'm looking to make a Schema for an XML report that has no restrictions at all on the order in which elements can appear, but has an element that must appear once, elements that can appear once, and elements that can appear any number of times.

I created an XSD following the second answer to this question, as that solution (albeit ugly) should solve my problem. However, using Microsoft's xsd.exe tool to generate classes for the xsd or using XmlDocument.Validate() gave the following warning:

Schema validation warning: Multiple definition of element 'optional2' causes the content model to become ambiguous. A content model must be formed such that...

The error is at line 21, which is the second time 'optional2' appears in the xsd.

Below is what I had for my version of the second answer to the question I referenced earlier.

<xs:group name="unboundedElements">
    <xs:choice>
        <xs:element name="unbounded1" type="unbounded1Type"/>
        <xs:element name="unbounded2" type="unbounded2Type"/>
        <xs:element name="unbounded3" type="unbounded3Type"/>
        <xs:element name="unbounded4" type="unbounded4Type"/>
    </xs:choice>
</xs:group>
<xs:element name="root">
    <xs:complexType>
        <xs:sequence>
            <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
            <xs:choice>
                <xs:sequence>
                    <xs:element name="optional1" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional2" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional3" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional4" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="required" type="queryType" maxOccurs="1"/>
                </xs:sequence>
                <xs:sequence>
                    <xs:element name="optional2" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional1" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional3" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional4" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="required" type="queryType" maxOccurs="1"/>
                </xs:sequence>
                <xs:sequence>
                    <xs:element name="optional3" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional2" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional1" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="optional4" type="xs:string" maxOccurs="1" minOccurs="0"/>
                    <xs:group ref="unboundedElements" minOccurs="0" maxOccurs="unbounded"/>
                    <xs:element name="required" type="queryType" maxOccurs="1"/>
// And so on, since this is 5! = 120 permutations
                </xs:sequence>
           </xs:choice>
       </xs:sequence>
    </xs:complexType>
</xs:element>

I'm hoping that someone could point out and explain what I'm doing wrong.

I could "validate" the xml by just using a <xs:choice maxOccurs="unbounded"> tag around all the elements, as that would allow for the order to not matter, but it would not place any of the necessary restrictions on the xml document.

Also, I know xsd 1.1 allows using maxOccurs="unbounded" with <xs:all> which would solve the problem perfectly, but .NET doesn't support using xsd 1.1.

I'm thinking my best solution going forward would probably be to just sort of enforce strict ordering of elements by sorting the xml nodes before validating it (allowing the xsd document to be far simpler and correct), but I still want to learn more about xsd and try to figure out what's wrong with my attempt.

1 Answers1

0

If you want to have the nodes "optional1" ... "optional4" only once in a specific section (not several times and unsorted), then you have to define all possible orders with the first node mandatory in order to get rid of the ambiguity. You may have to follow this method several times. Hope this helps, Peter

  • In my xsd I do have all possible orders of optional1 through optional4 and the required elements (so 5 total elements, every permutation being 120 possible orders). Each permutation is within a sequence tag, and each of those sequence tags is within a choice tag. What do you mean by making the first node mandatory to get rid of the ambiguity? – Profesor Caos Jul 31 '17 at 19:41
  • When checking an xml document against an xml schema any program has to follow a kind of decision tree (which means to follow the path through the xml schema). At each point of the tree there should be only one possibility to follow this tree, so ambiguity is not allowed at any point. Using mandatory nodes can help you to avoid these situations. – Peter Raffelsberger Jul 31 '17 at 19:53
  • In order to be more precise I would need additional information about the possible combinations in your application like A-B-C-D-E and A-C-B-D-E is valid, but A-E-D-C-B is not valid. – Peter Raffelsberger Jul 31 '17 at 19:55