Схема XML для последовательности элементов с одинаковыми именами, но разными значениями атрибутов? - PullRequest
8 голосов
/ 06 мая 2009

Как я могу указать схему XML для экземпляра документа, как это:

<productinfo>
  <!-- other stuff -->
  <informationset type="Manufacturer">
    <!-- content not relevant -->
  </informationset>
  <informationset type="Ingredients">
    <!-- content not relevant -->
  </informationset>
</productinfo>

, то есть элемент productinfo, содержащий последовательность двух дочерних элементов «информационного набора», первый из которых имеет @type="Manufacturer", а второй - @type="Ingredients"?

Ответы [ 5 ]

3 голосов
/ 06 мая 2009

ПРИМЕЧАНИЕ этот ответ неверен, как указал Серж.

Тестирование с xerces выдает эту ошибку: type.xsd:3:21: cos-element-consistent: Error for type '#AnonType_productinfo'. Multiple elements with name 'informationset', with different types, appear in the model group. В спецификации есть больше деталей для согласованного с cos-элементом .

Но есть решение, похожее на ответ Марка ниже, но все еще использующее типы. Можно иметь несколько вхождений одного и того же с разными типами, если они находятся в списке супертипа minOccurs / maxOccurs, который расширен другими типами. То есть, как список полиморфных классов в Java или C #. Это устраняет проблему, указанную выше, поскольку, хотя это имя элемента может появляться в xml много раз, в xsd оно появляется только один раз.

Вот пример xsd и xml - проверено с xerces на этот раз!:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="productinfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="informationset" type="supertype" minOccurs="2" maxOccurs="2"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="supertype">
  </xs:complexType>

  <xs:complexType name="Manufacturer">
    <xs:complexContent>
      <xs:extension base="supertype">
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Ingredients">
    <xs:complexContent>
      <xs:extension base="supertype">
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

</xs:schema>

<productinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <informationset xsi:type="Manufacturer"></informationset>
  <informationset xsi:type="Ingredients"></informationset>
</productinfo>

ПРИМЕЧАНИЕ: Вы не можете контролировать порядок различных типов или сколько раз встречается каждый тип (каждый может появляться один раз, много раз или вообще не появляться) - так же, как с список полиморфных классов в Java или C #. Но вы можете, по крайней мере, указать точную длину списка в целом (если хотите).

Например, я ограничил приведенный выше пример ровно двумя элементами, но порядок не установлен (т. Е. Производитель может быть первым или Ingredients может быть первым); и число повторений не установлено (то есть они могут быть Производитель или оба Ингредиенты или по одному на каждый).


Вы можете с помощью XML Schema набрать , например:

<productinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <informationset xsi:type="Manufacturer"></informationset>
  <informationset xsi:type="Ingredients"></informationset>
</productinfo>

И XSD определяет отдельные сложные типы для каждого из них:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="productinfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="informationset" type="Manufacturer"/>
        <xs:element name="informationset" type="Ingredients"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="Manufacturer">
  </xs:complexType>
  <xs:complexType name="Ingredients">
  </xs:complexType>
</xs:schema>

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

Я не на 100% уверен в точной причине - кто-нибудь знает соответствующую часть спецификации?

2 голосов
/ 06 мая 2009

Вы можете попробовать что-то вроде этого - создать отдельный complexType для ваших элементов "informationSet" и ограничить атрибут списком допустимых строк:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" 
           xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="productinfo">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" 
                    name="informationset" type="informationSetType" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="informationSetType">
    <xs:simpleContent>
      <xs:extension base="xs:string">
        <xs:attribute name="type" type="validAttributeType" use="required" />
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>

  <xs:simpleType name="validAttributeType">
    <xs:restriction base="xs:string">
      <xs:enumeration value="Manufacturer" />
      <xs:enumeration value="Ingredients" />
    </xs:restriction>
  </xs:simpleType>
</xs:schema>

Конечно, вы можете расширить этот список допустимых имен атрибутов, если хотите - просто добавьте больше элементов в список ограничений-перечислений.

Марк

1 голос
/ 22 сентября 2015

Использование компонента схемы утверждений

Благодаря XML-схеме 1.1 существует способ реализовать ваше требование без необходимости импортировать пространство имен xsi и взламывать полиморфизм в ваш XML-документ. В XML Schema 1.1 появились два новых компонента: утверждения и альтернативы типа , обеспечивающие элементы xs:assert и xs:alternative. У них есть атрибут @test, в котором условия и ограничения задаются как выражения XPath 2.0 .


Несмотря на то, что xs:alternative, очевидно, предназначено для решения вашей проблемы, я, со своей стороны, пока не смог назначить альтернативные типы на основе позиции элемента. ( Понимание синтаксическим анализатором схемы контекстов узла, по-видимому, отличается от того, которое я ожидал бы, основываясь на проверенной структуре документа XML. )


В любом случае , вы можете применить свои ограничения, используя xs:assert:

<xs:element name="productinfo">
  <xs:complexType>
    <xs:sequence minOccurs="2" maxOccurs="unbounded">
      <xs:element name="informationset">
        <xs:complexType>
          <xs:attribute name="type" use="required">
            <xs:simpleType>
              <xs:restriction base="xs:string">
                <xs:enumeration value="Manufacturer" />
                <xs:enumeration value="Ingredients" />
              </xs:restriction>
            </xs:simpleType>
          </xs:attribute>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:assert test="informationset[1]/@type='Manufacturer'" xpathDefaultNamespace="##targetNamespace"/>
    <xs:assert test="informationset[2]/@type='Ingredients'" xpathDefaultNamespace="##targetNamespace"/>
  </xs:complexType>
</xs:element>

Использование атрибута @xpathDefaultNamespace может не потребоваться, если пространство имен вашей схемы равно нулю, но должно быть установлено на ##targetNamespace, если схема определяет его, иначе оценка имени элемента завершится неудачно.

Примечание: Очевидно, чтобы это работало, необходимо использовать валидатор, который поддерживает XML-схему 1.1. При использовании, скажем, OxygenXML, вы можете просто установить версию схемы XML по умолчанию на 1.1 на странице настроек XML / XML Parser / XML Schema . При использовании Xerces в качестве валидатора должна быть активирована дополнительная функция : http://apache.org/xml/features/validation/cta-full-xpath-checking. В противном случае он не сможет оценить большую часть XPath, которую вы придумали, поскольку он использует недостаточное подмножество по умолчанию.


0 голосов
/ 10 апреля 2015

В VS сообщает об ошибке: Элементы с одинаковым именем и в той же области видимости должны иметь одинаковый тип.
Я думаю, что XSD не может полностью удовлетворить ваше требование, вы можете попытаться решить его с другого направления. Например, используйте xslt для проверки XML. XSLT основан на xpath и правилах, он может проверять все места в xml.
XSD + XSLT - хорошее решение, XSD для проверки схемы, XSLT для проверки информации.

0 голосов
/ 28 февраля 2011

Может быть, http://xsd.stylusstudio.com/2001Aug/post03013.htm - это то, что вы ищете.

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