XSD — как описать неупорядоченный набор типов элементов, где первый элемент должен появиться первым в последовательности?

Это вопрос по схеме XML.

Я знаю, что элемент xsd:all не может появляться в последовательности (должен быть элементом верхнего уровня своего типа).

То есть я не могу использовать следующее:

<xsd:complexType name="Application">
  <xsd:sequence>
    <xsd:element ref="Name"></xsd:element>
    <xsd:all>
      <xsd:element ref="ADD"></xsd:element>
      <xsd:element ref="DELETE"></xsd:element>
    </xsd:all>
  </xsd:sequence>
</xsd:complexType>

Мой вопрос заключается в том, как объявить элементы «ADD» и «DELETE» выше в любом порядке (неупорядоченный набор), но при этом убедиться, что элемент «Name» будет первым и всегда будет отображаться. (Подумайте о ситуации, когда у меня есть не только «ДОБАВИТЬ» и «УДАЛИТЬ», но и около 10 или более неупорядоченных элементов: ДОБАВИТЬ, УДАЛИТЬ, РЕДАКТИРОВАТЬ и т. Д.)

ВАЖНОЕ ПРИМЕЧАНИЕ: ДОБАВИТЬ и УДАЛИТЬ могут появиться только ОДИН РАЗ, но их порядок не имеет значения:

<Application>
  <NAME>
   <DELETE>
   <ADD>
</Application>

но нет:

<Application>
  <NAME>
  <DELETE>
  <ADD>
  <DELETE> <!--cannot appear twice-->
</Application>

person ogee    schedule 06.01.2009    source источник


Ответы (5)


Если я понимаю ваш запрос, вы правы, единственное, чего вам не хватает, это maxOccurs="unbounded" по вашему выбору.

Я создал следующую схему:

<?xml version="1.0"?>
<xs:schema targetNamespace="http://someNamespace" xmlns="http://someNamespace" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Root" type="Application">
  </xs:element>

  <xs:complexType name="Application">
    <xs:sequence>
      <xs:element ref="Name"></xs:element>
      <xs:choice maxOccurs="unbounded">
        <xs:element ref="ADD"></xs:element>
        <xs:element ref="DELETE"></xs:element>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>

  <xs:element name="Name"/>
  <xs:element name="ADD"/>
  <xs:element name="DELETE"/>
</xs:schema>

И это хорошо сработало для

<ns0:Root xmlns:ns0="http://someNamespace">
  <ns0:Name />
  <ns0:ADD />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:DELETE />
</ns0:Root>

но не для

<ns0:Root xmlns:ns0="http://someNamespace">
  <ns0:ADD />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:ADD />
  <ns0:DELETE />
  <ns0:DELETE />
</ns0:Root>
person Yossi Dahan    schedule 06.01.2009
comment
Большое спасибо за ваш ответ. Я отлично настроил свой вопрос выше. Я имел в виду, что ADD и DELETE не должны появляться 0 или 1 раз, но их порядок не имеет значения. all нельзя использовать в этом случае, потому что обязательный элемент NAME не может идти со всеми. У вас есть другое решение? Благодарить - person ogee; 06.01.2009
comment
Работает только с атрибутом maxOccurs=unbounded для тега выбора. - person Pooya; 08.07.2012

Я думаю, вы ищете элемент «все», он допускает неупорядоченный список. Однако существуют ограничения на элементы, которые вы можете туда поместить. См. http://www.w3.org/2005/07/xml-schema-patterns.html#Collection

person Dirkjan Krijnders    schedule 05.02.2010
comment
‹xs:choice maxOccurs=unbounded minOccurs=1› также описывает неупорядоченный список. - person lbalazscs; 27.09.2012

Мне жаль, что вы мучаетесь с этой проблемой уже 7 лет без ответа.

Я собираюсь помочь, пересмотрев ваши предположения.

Рассматривая «Имя» как элемент данных, который должен быть первым, и требуя, чтобы он был дочерним элементом приложения, а затем в целом говоря, что вас не волнует порядок его братьев и сестер, вы создаете запутанную ситуацию. для себя. Почему Name является братом ADD и DELETE, если оно следует другим правилам и служит другой цели? Если бы вам пришлось моделировать это в любой другой структуре данных, вы бы не включили «Имя» в список вещей вместе с «ДОБАВИТЬ» и «УДАЛИТЬ». Вы бы сказали две вещи: у приложения есть имя, а также список команд, таких как ADD и DELETE.

Поскольку имя — это особая вещь по сравнению с ADD и DELETE, его следует моделировать отдельно от этих других тегов.

Таким образом, вы можете сделать Name атрибутом Application и оставить Add и Delete в качестве дочерних элементов, или вы можете оставить Name в качестве дочернего элемента, но затем окружить ADD и DELETE тегом-заполнителем/группировкой, таким как Commands. Тег Commands будет единственным братом Name.

Вот схема, поддерживающая Name в качестве атрибута с произвольным количеством команд в любом порядке. «Имя как атрибут.xsd»:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Application" type="Application_Type" />
    <xs:complexType name="Application_Type">
            <xs:all>
                <xs:element minOccurs="0" ref="ADD"/>
                <xs:element minOccurs="0" ref="DELETE"/>
                <xs:element minOccurs="0" ref="THIRD"/>
                <xs:element minOccurs="0" ref="FOURTH"/>
            </xs:all>
            <xs:attribute name="Name"/>
    </xs:complexType>
    <xs:element name="ADD"/>
    <xs:element name="DELETE"/>
    <xs:element name="THIRD"/>  
    <xs:element name="FOURTH"/> 
</xs:schema>

Пример XML:

<?xml version="1.0" encoding="UTF-8"?>
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="text" xsi:noNamespaceSchemaLocation="Name as Attribute.xsd">
    <THIRD>text</THIRD>
    <ADD>text</ADD>
    <FOURTH>text</FOURTH>
    <DELETE>text</DELETE>
</Application>

А вот один с командами, вложенными в тег-заполнитель. "Группировка команд.xsd":

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="Application" type="Application_Type"/>
    <xs:complexType name="Application_Type">
        <xs:sequence>
            <xs:element ref="Name"/>
            <xs:element name="Commands" type="Commands_Type"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Commands_Type">
        <xs:all>
            <xs:element minOccurs="0" ref="ADD"/>
            <xs:element minOccurs="0" ref="DELETE"/>
            <xs:element minOccurs="0" ref="THIRD"/>
            <xs:element minOccurs="0" ref="FOURTH"/>
        </xs:all>
    </xs:complexType>
    <xs:element name="Name"/>
    <xs:element name="ADD"/>
    <xs:element name="DELETE"/>
    <xs:element name="THIRD"/>
    <xs:element name="FOURTH"/>
</xs:schema>

Пример XML:

<?xml version="1.0" encoding="UTF-8"?>
<Application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Commands Grouping.xsd">
    <Name>text</Name>
    <Commands>
        <THIRD>text</THIRD>
        <ADD>text</ADD>
        <FOURTH>text</FOURTH>
        <DELETE>text</DELETE>
    </Commands>
</Application>

Одно замечание по поводу любого из них заключается в том, что сообщения с нулевыми командами по-прежнему являются действительными сообщениями. Возможно, это нормально, но если это проблема, возможно, эта проверка принадлежит прикладному уровню, а не XSD.

person James Daily    schedule 06.06.2016

Я не верю, что это можно сделать без перечисления всех комбинаций ADD, DELETE и т. д. Вообще говоря, неупорядоченные списки плохо работают ни с DTD, ни со схемами.

person Alohci    schedule 08.01.2009
comment
‹xs:choice maxOccurs=unbounded minOccurs=1› описывает неупорядоченный список - person lbalazscs; 27.09.2012
comment
@lbalazscs - Из вопроса ВАЖНОЕ ПРИМЕЧАНИЕ: ДОБАВИТЬ и УДАЛИТЬ могут появиться только ОДИН РАЗ, но их порядок не имеет значения:. maxOccurs=unbounded этого не доставляет. - person Alohci; 27.09.2012
comment
Alhoci, да, ОП хотел неупорядоченный НАБОР, но неупорядоченные СПИСКИ все еще возможны. Я добавил этот комментарий, потому что ваш ответ ввел меня в заблуждение (у меня была другая проблема, когда элементы могли появляться в любое время), только чтобы позже обнаружить, что неупорядоченные списки абсолютно возможны. - person lbalazscs; 27.09.2012

Вы можете реализовать ненумерованные списки, используя тип последовательности xs:choice.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xs:element name="Application"/>
  <xs:complexType>
   <xs:element name="NAME">
    <xs:sequence>
     <xs:choice minOccurs="0" maxOccurs="unbounded">
      <xs:element name="ADD" type="xs:string"/>
      <xs:element name="DELETE" type="xs:string"/>
     </xs:choice>
    </xs:element>
   </xs:sequence>
  </xs:complexType>
 </xs:element>
</xs:schema>

Таким образом, вы запрещаете пользователю использовать любой тег внутри элемента <NAME/>, но позволяете ему использовать <ADD/> и <DELETE/> так часто, как он хочет.

person Daniel Lee    schedule 26.11.2014
comment
Действительно ли в этом случае <xs:sequence> там действительно необходимо? - person LarsH; 16.05.2016
comment
@LarsH: Да, поскольку xs:choice позволяет выбрать только один из перечисленных элементов. xs:sequence здесь создает неограниченный/повторяющийся выбор ADD или DELETE. Однако это не соответствует требованию OP никогда не разрешать более одного экземпляра ADD и DELETE за раз. - person James Daily; 06.06.2016