XSD - как разрешить элементы в любом порядке любое количество раз?

99

Я пытаюсь создать XSD и пытаюсь написать определение со следующим требованием:

  • Разрешить указанный дочерний элемент появляться любое количество раз (от 0 до неограниченного)
  • Разрешить дочерние элементы в любом порядке

Я посмотрел вокруг и нашел различные решения, как это:

<xs:element name="foo">
  <xsl:complexType>
    <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="child1" type="xs:int"/>
      <xs:element name="child2" type="xs:string"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

Но из того, что я понимаю, xs: choice по-прежнему позволяет выбирать только один элемент. Следовательно, установка MaxOccurs на неограниченное значение, подобное этому, должна означать только то, что "любой" из дочерних элементов может появляться несколько раз. Это точно?

Если приведенное выше решение неверно, как я могу добиться того, что я изложил выше в своем требовании?

РЕДАКТИРОВАТЬ: Что делать, если требование заключается в следующем?

  • Элемент child1 child2 может появляться любое количество раз (от 0 до неограниченного)
  • Элементы должны быть в любом порядке
  • Элементы child3 и child4 должны появляться ровно один раз.

Например, этот xml действителен:

<foo>
<child1> value </child1>
<child1> value </child1>
<child3> value </child3>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>

но это не так (отсутствует child3)

<foo>
<child1> value </child1>
<child1> value </child1>
<child2> value </child2>
<child4> value </child4>
<child1> value </child1>
</foo>
Теги:
xsd

6 ответов

52
Лучший ответ

В схеме, которая у вас есть в вашем вопросе, child1 или child2 может появляться в любом порядке, любое количество раз. Так что это похоже на то, что вы ищете.

Изменить:, если вы хотите, чтобы только один из них отображался неограниченное количество раз, безграничные должны были бы включать элементы:

Изменить: Фиксированный тип в XML.

Изменить: Заглавная O в maxOccurs

<xs:element name="foo">
   <xs:complexType>
     <xs:choice maxOccurs="unbounded">
       <xs:element name="child1" type="xs:int" maxOccurs="unbounded"/>
       <xs:element name="child2" type="xs:string" maxOccurs="unbounded"/>
     </xs:choice>
   </xs:complexType>
</xs:element>
  • 0
    в основном да, я ищу элементы child1, child2, которые должны появляться в любом порядке, любое количество раз .. ответ, который вы здесь предоставили, работает только для одного элемента, верно? или это также решает мое требование?
  • 0
    Схема в вашем вопросе соответствует вашему требованию; альтернативная схема в моем ответе для одного элемента. Надеюсь, что это прояснилось! :)
Показать ещё 4 комментария
96

Альтернативная формулировка вопроса, добавленного в более позднем редактировании, по-прежнему остается без ответа: как указать, что среди дочерних элементов элемента должен быть один с именем child3, один с именем child4, и любое число с именем child1 или child2, без ограничения на порядок появления детей.

Это простой и понятный регулярный язык, и требуемая модель контента изоморфна регулярному выражению, определяющему набор строк, в которых цифры "3" и "4" встречаются ровно один раз, а цифры "1" и "2" происходит любое количество раз. Если это не очевидно, как написать это, это может помочь подумать о том, какой конечный автомат вы построили для распознавания такого языка. Он имел бы как минимум четыре разных состояния:

  • начальное состояние, в котором не было ни "3" , ни "4"
  • промежуточное состояние, в котором "3" было замечено, но не "4"
  • промежуточное состояние, в котором "4" было замечено, но не "3"
  • конечное состояние, в котором были замечены как "3" , так и "4"

Независимо от того, в каком состоянии находится автомат, можно прочитать "1" и "2" ; они не меняют состояние машины. В начальном состоянии также будут приняты "3" или "4" ; в промежуточных состояниях принимаются только "4" или "3" ; в конечном состоянии, ни "3" , ни "4" не принимаются. Структура регулярного выражения проще всего понять, если мы сначала определим регулярное выражение для подмножества нашего языка, в котором встречаются только "3" и "4" :

(34)|(43)

Чтобы позволить "1" или "2" появляться любое количество раз в определенном месте, мы можем вставить (1|2)* (или [12]*, если наш язык регулярных выражений принимает эту нотацию). Вставив это выражение во все доступные места, мы получим

(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*

Переводить это в модель контента просто. Базовая структура эквивалентна регулярному выражению (34)|(43):

<xsd:complexType name="paul0">
  <xsd:choice>
    <xsd:sequence>
      <xsd:element ref="child3"/>
      <xsd:element ref="child4"/>
    </xsd:sequence>
    <xsd:sequence>
      <xsd:element ref="child4"/>
      <xsd:element ref="child3"/>
    </xsd:sequence>
  </xsd:choice>
</xsd:complexType>

Вставка нулевого или большего выбора child1 и child2 прост:

<xsd:complexType name="paul1">
  <xsd:sequence>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
  </xsd:sequence>
</xsd:complexType>

Если мы хотим минимизировать объем бит, мы можем определить именованную группу для повторяющихся вариантов child1 и child2:

<xsd:group name="onetwo">
  <xsd:choice>
    <xsd:element ref="child1"/>
    <xsd:element ref="child2"/>
  </xsd:choice>   
</xsd:group>

<xsd:complexType name="paul2">
  <xsd:sequence>
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>  
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

В XSD 1.1 некоторые ограничения на all -группы были сняты, поэтому можно более кратко определить эту модель контента:

<xsd:complexType name="paul3">
  <xsd:all>
    <xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child3"/>
    <xsd:element ref="child4"/>      
  </xsd:all>
</xsd:complexType>

Но, как видно из приведенных ранее примеров, эти изменения в all -группы фактически не изменяют выразительную силу языка; они лишь упрощают определение некоторых видов языков.

  • 2
    Мне нравится XSD 1.0 xs: все альтернативы.
  • 8
    +1. Это отличный ответ, и он заслуживает большего количества голосов.
Показать ещё 5 комментариев
45

Вот что, наконец, помогло мне:

<xsd:element name="bar">
  <xsd:complexType>
    <xsd:sequence>
      <!--  Permit any of these tags in any order in any number     -->
      <xsd:choice minOccurs="0" maxOccurs="unbounded">
        <xsd:element name="child1" type="xsd:string" />
        <xsd:element name="child2" type="xsd:string" />
        <xsd:element name="child3" type="xsd:string" />
      </xsd:choice>
    </xsd:sequence>
  </xsd:complexType>
</xsd:element>
  • 5
    На самом деле хитрость заключается в использовании xsd: choice с квантификаторами <xsd: choice minOccurs = "0" maxOccurs = "unbounded">
  • 6
    Я думаю, что стоит отметить, что приведенный выше пример работает даже без элемента sequence, включающего элемент choice.
8

Но из того, что я понимаю xs: выбор по-прежнему допускает только выбор одного элемента. Следовательно, установка MaxOccurs неограниченно, как это должно означать только то, что "любой" дочерних элементов может появляться несколько раз. Это точно?

Нет. Выбор происходит индивидуально для каждого "повторения" xs:choice, который возникает из-за maxOccurs="unbounded". Таким образом, код, который вы опубликовали, является правильным, и на самом деле будет делать то, что вы хотите, как написано.

  • 0
    Ваш комментарий с ответом, предоставленным @Alan, объясняет все это хорошо.
3

Вы должны найти, что следующая схема позволяет то, что вы предложили.

  <xs:element name="foo">
    <xs:complexType>
      <xs:sequence minOccurs="0" maxOccurs="unbounded">
        <xs:choice>
          <xs:element maxOccurs="unbounded" name="child1" type="xs:unsignedByte" />
          <xs:element maxOccurs="unbounded" name="child2" type="xs:string" />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

Это позволит вам создать файл, например:

<?xml version="1.0" encoding="utf-8" ?>
<foo>
  <child1>2</child1>
  <child1>3</child1>
  <child2>test</child2>
  <child2>another-test</child2>
</foo>

Что похоже на ваш вопрос.

  • 0
    minOccurs и maxOccurs ограничены 1 для детей xs:all .
  • 0
    Павел: Спасибо ... Я узнал об этом после двойной проверки моего поста, а затем отредактировал его, чтобы удалить xs: all
1

Если ни одно из вышеперечисленных действий не работает, вы, вероятно, работаете над EAS trasaction, где вам нужно проверить ваш результат по схеме HIPPA или любому другому сложному xsd. Требование состоит в том, что, скажем, существует 8 сегментов REF, и любой из них должен появляться в любом порядке, а также не все они требуются, означает, что вы можете иметь их в следующем порядке: 1-й REF, 3 REF, 2 REF, 9-й REF. В ситуации по умолчанию получение EDI не будет выполнено, beacause по умолчанию сложный тип

<xs:sequence>
  <xs:element.../>
</xs:sequence>

Ситуация даже сложна, когда вы вызываете свой элемент по refrence, а затем этот элемент в его исходном месте довольно сложный. например:

<xs:element>
<xs:complexType>
<xs:sequence>
<element name="REF1"  ref= "REF1_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF2"  ref= "REF2_Mycustomelment" minOccurs="0" maxOccurs="1">
<element name="REF3"  ref= "REF3_Mycustomelment" minOccurs="0" maxOccurs="1">
</xs:sequence>
</xs:complexType>
</xs:element>

Решение:

Здесь просто замена "sequence" на "all" или использование "choice" с комбинациями min/max не будет работать!

Первое, что нужно заменить "xs:sequence" with "<xs:all>" Теперь вам нужно внести некоторые изменения, когда вы ссылаетесь на элемент, Перейдите к:

<xs:annotation>
  <xs:appinfo>
    <b:recordinfo structure="delimited" field.........Biztalk/2003">

*** Теперь в вышеприведенном сегменте добавьте триггерную точку в конце, как это trigger_field = "REF01 _... полное имя.." trigger_value = "38" Сделайте то же самое для других сегментов REF, где значение триггера будет отличаться, например, "18", "XX", "YY" и т.д., Так что ваша информация о записи теперь выглядит следующим образом: b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


Это сделает каждый элемент уникальным, поскольку все REF-сегменты (пример выше) имеют такую ​​же структуру, как REF01, REF02, REF03. И во время проверки валидация структуры в порядке, но она не позволяет повторять значения, поскольку она пытается искать оставшиеся значения в первом REF. Добавление триггеров сделает их уникальными, и они пройдут в любом порядке и ситуационных случаях (например, используйте 5 из 9 и не все 9/9).

Надеюсь, это поможет вам, потому что я потратил почти 20 часов на это.

Удача

Ещё вопросы

Сообщество Overcoder
Наверх
Меню