Различные подэлементы в зависимости от значения атрибута / элемента - PullRequest
3 голосов
/ 11 мая 2010

Еще один вопрос XSD - как мне добиться того, чтобы следующие XML-элементы были действительными:

<some-element>
  <type>1</type>
  <a>...</a>
</some-element>

<some-element>
  <type>2</type>
  <b>...</b>
</some-element>

Подэлементы ( либо <a> или <b>) должны зависеть от содержимого <type> (также может быть атрибутом). Это было бы так просто в RelaxNG - но RelaxNG не поддерживает целостность ключа: (

Есть ли способ реализовать это в XSD?

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

<type>1</type>
<some-element type="1">
    <!-- simple <xs:choice> between <a> and <b> goes here -->
    <a>...</a>
</some-element>
<!-- and now create a keyref between <type> and @type -->

Ответы [ 2 ]

3 голосов
/ 11 мая 2010

Лучшее решение состоит в том, чтобы удалить элемент <type/> и иметь только xs:choice для <a/> и <b/> и позволить приложению, использующему xml, отсортировать тип.

Другое решение может заключаться в том, чтобы xs:choice для <a/> и <b/> использовать скрипт xslt для проверки правильности элемента <type/> в отношении <a/> и <b/>.

Сначала проверьте xml по xmlschema, затем используйте xslt, чтобы выполнить преобразование для него, если результатом преобразования является пустая строка, в противном случае будет показана полученная строка в виде сообщения об ошибке.

Как то так ...

XmlSchema:

  <xs:element name="some-element">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="type" type="xs:integer" />
        <xs:choice>
          <xs:element name="a" type="xs:string" />
          <xs:element name="b" type="xs:string" />
        </xs:choice>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:demo="uri:demo:namespace">
  <xsl:output method="text" />
  <xsl:template match="/demo:some-element">
    <xsl:if test="type = 1 and not(demo:a)">
      When type equals 1 element a is requred.
    </xsl:if>
    <xsl:if test="type = 2 and not(demo:b)">
      When type equals 2 element b is requred.
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
2 голосов
/ 11 мая 2010

Нет, XML Schema 1.0 не может этого сделать.

...