Как определить несколько элементов с одинаковым именем, но разным типом в элементе xsd: choice? - PullRequest
14 голосов
/ 18 марта 2010

Можно ли каким-то образом определить схему xsd, которая могла бы проверять такой xml:

<item_list>
  <item ItemType="SimpleMessage" Caption="Simplest message"/>
  <item ItemType="ComplexMessage" SomeAttr="value">
    <item_data>some text</item_data>
  </item>
</item_list>

Проблема в том, что я не нашел возможности определить что-то вроде:

  <xsd:element name="Items">
      <xsd:complexType>
        <xsd:choice>
          <xsd:element name="item" type="SimpleMessType"/>
          <xsd:element name="item" type="ComplexMessType"/>
        </xsd:choice>
      </xsd:complexType>
  </xsd:element>

Но мне нужно проверить, что SimpleMessage не имеет дочерних элементов или дополнительных атрибутов: (

Ответы [ 3 ]

7 голосов
/ 18 августа 2012

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

XSD 1.1 включает в себяконструкция, облегчающая поддержку таких случаев, как этот, для людей, которые по какой-либо причине не хотят использовать xsi:type таким образом: условное присвоение типа.По сути, это позволяет объявлению элемента иметь простую последовательность пар XPath / typename;Выражения XPath оцениваются последовательно, и когда значение равно true, элемент ассоциируется с соответствующим типом.В XPath есть ограничения, запрещающие заглядывать в потомки элемента или просматривать или просматривать другие части документа XML (первое помогает узнать, как только сканирование обнаружит начальный тег, тип которогоиспользуется для проверки элемента; второй помогает сохранить проверку без контекста), поэтому по существу тесты могут быть только проверками значений атрибутов.Ваш пример может быть написан так:

<xs:element name="item">
  <xs:alternative test="@ItemType='SimpleMessage'" type="SimpleMessType"/>
  <xs:alternative test="@ItemType='SimpleMessage'" type="ComplexMessType"/>
  <xs:alternative type="xs:error"/>
</xs:element>

Третий вариант гарантирует, что один из ваших ожидаемых случаев должен встретиться, чтобы элемент был действительным.Если бы он здесь был опущен, то, если ни одно из тестовых выражений не было истинным, элементу был бы присвоен объявленный тип item, в данном случае xs:anyType.

5 голосов
/ 22 марта 2010

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

В качестве обходного пути вы можете объединить определения типов SimpleMessType и ComplexMessType в один тип с mixed = "true" - и затем распутайте содержимое, которое вы получите, в своем собственном коде после завершения обработки схемы. См. Обсуждение в стеке потока о XSD-схеме для рекурсивного XML .

0 голосов
/ 22 марта 2010

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

Один из возможных вариантов для вас - определить супертип, скажем BaseElement, который будет пустым, а затем подтипы, и использовать xsi:type для переопределения вместо обычного атрибута type. Больше информации о том, как это работает, можно найти здесь .

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