Как создать схему для неупорядоченного списка узлов XML с ограничениями вхождения - PullRequest
17 голосов
/ 01 августа 2010

Принимая во внимание такую ​​структуру XML, я пытаюсь создать схему XSD для ее проверки.

<RootNode>
  <ChildA />
  <ChildC />
  <ChildB />
  <ChildB />
  <ChildA />
</RootNode>

Требования следующие:

  • ChildA, ChildBи ChildC может встречаться в любом порядке .(<xs:sequence> не подходит)
  • ChildA имеет значение обязательно , но может встречаться несколько раз.
  • ChildB является необязательным и может встречаться несколько раз.опционально и может встречаться только один раз .

Метод, который я обычно использую для создания неупорядоченного списка узлов, заключается в использовании <xs:choice maxOccurs="unbounded"> с каждым возможным узлом в списке, однакоЯ не могу создать ограничение minOccurs="1" для ChildA и ограничение maxOccurs="1" для ChildC.(Количество вариантов выбора имеет приоритет над числом элементов здесь).

<xs:element name="RootNode">
  <xs:complexType>
    <xs:choice minOccurs="1" maxOccurs="unbounded">
      <xs:element name="ChildA" minOccurs="1"/>
      <xs:element name="ChildB" />
      <xs:element name="ChildC" maxOccurs="1"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

Ответы [ 3 ]

11 голосов
/ 20 августа 2010

Обновление : В XSD 1.1m некоторые ограничения на all -группы были сняты.См. Ответы здесь и здесь .

Не простой, но кажется выполнимым.Сложной частью здесь является то, что определения схемы должны быть детерминированными.Подход, который я использовал, состоял в том, чтобы визуализировать проблему, нарисовав ее конечные автоматы, а затем написать регулярное выражение, соответствующее этим автоматам.Это совсем не так сложно, как может показаться.Тем не менее, использование некоторой другой системы проверки могло бы дать более простой ответ.

Я провел некоторое тестирование, но пропустить некоторые особые случаи легко.Пожалуйста, прокомментируйте, если обнаружите ошибку.

... и вот код:

<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>
2 голосов
/ 04 июня 2012

Это должно сделать то, что вы указали:

<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> 
1 голос
/ 26 января 2012

Я только что прочитал синтаксис relax-NG .

Я предполагаю, что в компактном синтаксисе relax-ng это будет сведено к следующему:

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

Конечно, это мило.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...