Как создать схему для незаказанного списка узлов XML с ограничениями возникновения

Учитывая расположение XML как это, я пытаюсь создать схему XSD для проверки его.

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

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

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

Техника, которую я обычно использую для создания незаказанного списка узлов, состоит в том, чтобы использовать a <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>
17
задан Cœur 30 April 2017 в 14:54
поделиться

1 ответ

Update: В 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>
11
ответ дан 30 November 2019 в 14:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: