How to create a schema for an unordered list of XML nodes, with occurrence constraints

前端 未结 3 1645
生来不讨喜
生来不讨喜 2020-12-10 12:05

Given an XML layout like this, I\'m trying to create a XSD schema to validate it.


  
  
  
          


        
相关标签:
3条回答
  • 2020-12-10 12:19

    Update: In XSD 1.1m some of the constraints on all-groups have been lifted. See the answers here and here.

    Not a simple one but seems doable. Difficult part here is that Schema definitions must be deterministic. Approach I used was to visualize the problem by drawing a finite state automata of it and then to write a regular expression that corresponded that automata. It is not at all as complicated as it might sound. Still, using some other validation system would have likely provided simpler answer.

    I have done some testing but missing out some special cases is easy. Please comment if you spot an error.

    ...and here is the code:

    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
    
        <!-- Schema for elements ChildA, ChildB and ChildC
            The requirements are as follows:
                * ChildA, ChildB and ChildC may occur in any order.
                * ChildA is mandatory but may occur multiple times.
                * ChildB is optional and may occur multiple times.
                * ChildC is optional and may occur once only.
        -->
    
        <xsd:element name="root">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element name="ABC-container" type="ABC" maxOccurs="unbounded"/>
                </xsd:sequence>
            </xsd:complexType>
        </xsd:element>
    
        <xsd:complexType name="ABC">
            <xsd:sequence>
                <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:choice>
                    <xsd:sequence maxOccurs="1">
                        <xsd:element name="ChildC" type="xsd:string"/>
                        <xsd:element name="ChildB" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
                        <xsd:element name="ChildA" type="xsd:string"/>
                        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                            <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/>
                            <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/>
                        </xsd:sequence>
                    </xsd:sequence>
                    <xsd:sequence maxOccurs="1">
                        <xsd:element name="ChildA" type="xsd:string" minOccurs="1"/>
                        <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                            <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/>
                            <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/>
                        </xsd:sequence>
                        <xsd:sequence minOccurs="0" maxOccurs="1">
                            <xsd:element name="ChildC" type="xsd:string"/>
                            <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                                <xsd:element name="ChildA" type="xsd:string" minOccurs="0"/>
                                <xsd:element name="ChildB" type="xsd:string" minOccurs="0"/>
                            </xsd:sequence>
                        </xsd:sequence>
                    </xsd:sequence>
                </xsd:choice>
            </xsd:sequence>
        </xsd:complexType>
    
    </xsd:schema>
    
    0 讨论(0)
  • 2020-12-10 12:20

    I was just reading the relax-NG shortcut syntax.

    I'm guessing this would be condensed to the following in relax-ng's compact syntax:

    head = element root { ChildA & ChildC? & ChildB* }
    

    That sure is pretty.

    0 讨论(0)
  • 2020-12-10 12:21

    This should do what you specified:

    <xs:element name="RootNode">   
      <xs:complexType>     
        <xs:all>       
          <xs:element name="ChildA" minOccurs="1"/>      
          <xs:element name="ChildB" />       
          <xs:element name="ChildC" minOccurs="0" maxOccurs="1"/>     
        </xs:all>   
      </xs:complexType> 
    </xs:element> 
    
    0 讨论(0)
提交回复
热议问题