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


Я пытаюсь создать 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:выбор по-прежнему позволяет выбирать только один элемент. Следовательно, установка MaxOccurs to Unbound like this должно означать только то, что" любой " из дочерних элементов может появляться несколько раз. Это точно?

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

EDIT: что делать, если требование заключается в следующем?

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

например, этот 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>
6 96

6 ответов:

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

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

Edit: фиксированный тип в XML.

Edit: заглавная 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>

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

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

  • начальное состояние, в котором не было видно ни '3', ни '4'
  • промежуточное состояние, в котором " 3 "было замечено, но не "4"
  • an промежуточное состояние, в котором " 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>

но как видно из примеров учитывая ранее, эти изменения в

вот что, наконец, сработало для меня:

<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>

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

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

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

  <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>

который, кажется, соответствует вашему вопросу.

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

<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>

устранение:

здесь просто заменить " последовательность "на" все "или использовать" выбор " с минимальными/максимальными комбинациями не будет работать!

первым делом заменить "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" etc..so что ваша информация о записи теперь выглядит так:b:recordinfo structure="delimited" field.........Biztalk/2003" trigger_field="REF01_...complete name.." trigger_value="38">


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

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

Удачи