Сложные правила в XSD для последовательности элементов - PullRequest
1 голос
/ 26 июня 2009

В моем XML у меня есть 6 элементов X1, X2, X3, X4, X5 и X6. Правила следующие -

X1 должен сопровождаться X2

X2 должен сопровождаться X3

X3 должен сопровождаться X4

X4 должен сопровождаться X2, X3, X4 или X5

X5 должен сопровождаться X6

X6 может сопровождаться X2, X3, X4, X5 или X6

Я пытаюсь определить XSD для этого. Является ли это возможным? Я пробовал несколько вещей, используя sequence и minOccur и maxOccur, но не работал. Любые идеи, которые я могу попробовать?

Ответы [ 2 ]

4 голосов
/ 26 июня 2009

XML Schema 1.0 не может обработать этот случай. Schematron, с другой стороны, напрямую переводит ваши ограничения, см. Рабочую / проверенную схему Schematron ниже:

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
  <pattern>
    <rule context="X1">
      <assert test="following-sibling::*[1][self::X2]">
        X1 must be followed by X2
      </assert>
    </rule>
    <rule context="X2">
      <assert test="following-sibling::*[1][self::X3]">
        X2 must be followed by X3
      </assert>
    </rule>
    <rule context="X3">
      <assert test="following-sibling::*[1][self::X4]">
        X3 must be followed by X4
      </assert>
    </rule>
    <rule context="X4">
      <assert test="following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5]">
        X4 must be followed by X2, X3, X4 or X5
      </assert>
    </rule>
    <rule context="X5">
      <assert test="following-sibling::*[1][self::X6]">
        X5 must be followed by X6
      </assert>
    </rule>
    <rule context="X6">
      <assert test="not(following-sibling::*) or following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5 or self::X6]">
        X6 can be followed by X2, X3, X4, X5 or X6
      </assert>
    </rule>
  </pattern>
</schema>

XML Schema 1.1 добавит поддержку утверждений, но у нее есть некоторые ограничения в области действия, к которой относится утверждение XPath - вам нужно будет поместить утверждения в родительский элемент X1..X6.

Обратите внимание, что правила Schematron могут оставаться встроенными в XML-схему внутри xs: annotation / xs: appinfo, и вы должны иметь возможность проверять как XML-схему, так и встроенные правила Schematron.

Продолжение после комментария ОП

Ниже приведена схема XML, в которую встроены вышеуказанные правила Schematron. Это образец, который определяет тест элемента, который может содержать X1..X6.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:sch="http://purl.oclc.org/dsdl/schematron">
  <xs:annotation>
    <xs:appinfo>
      <sch:title>Sample embedded Schematron rules</sch:title>
    </xs:appinfo>
  </xs:annotation>
  <xs:element name="test">
    <xs:annotation>
      <xs:appinfo>
        <sch:pattern>
          <sch:rule context="X1">
            <sch:assert test="following-sibling::*[1][self::X2]"> X1 must be followed by X2 </sch:assert>
          </sch:rule>
          <sch:rule context="X2">
            <sch:assert test="following-sibling::*[1][self::X3]"> X2 must be followed by X3 </sch:assert>
          </sch:rule>
          <sch:rule context="X3">
            <sch:assert test="following-sibling::*[1][self::X4]"> X3 must be followed by X4 </sch:assert>
          </sch:rule>
          <sch:rule context="X4">
            <sch:assert test="following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5]"> X4
              must be followed by X2, X3, X4 or X5 </sch:assert>
          </sch:rule>
          <sch:rule context="X5">
            <sch:assert test="following-sibling::*[1][self::X6]"> X5 must be followed by X6 </sch:assert>
          </sch:rule>
          <sch:rule context="X6">
            <sch:assert
              test="not(following-sibling::*) or following-sibling::*[1][self::X2 or self::X3 or self::X4 or self::X5 or self::X6]"
              > X6 can be followed by X2, X3, X4, X5 or X6 </sch:assert>
          </sch:rule>
        </sch:pattern>
      </xs:appinfo>
    </xs:annotation>
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element ref="X1"/>
        <xs:element ref="X2"/>
        <xs:element ref="X3"/>
        <xs:element ref="X4"/>
        <xs:element ref="X5"/>
        <xs:element ref="X6"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>

  <xs:element name="X1"/>
  <xs:element name="X2"/>
  <xs:element name="X3"/>
  <xs:element name="X4"/>
  <xs:element name="X5"/>
  <xs:element name="X6"/>
</xs:schema>

Экземпляр документа может выглядеть следующим образом:

<?oxygen SCHSchema="test.xsd"?>
<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="test.xsd">
  <X1/>
  <X2/>
  <X3/>
  <X4/>
  <X4/>
  <X3/>
  <X4/>
  <X5/>
  <X6/>
  <X4/>
  <X5/>
  <X6/>
</test>

Выше тестируется с oXygen XML Editor. Экземпляр связывает XML-схему также с инструкцией обработки, чтобы сообщить oXygen, что схема содержит встроенные правила Schematron. Проверка выполняется как по схеме XML, так и по правилам Schematron.

1 голос
/ 26 июня 2009

Как бы то ни было, вот пример решения, предполагая, что X6 может быть конечным элементом, а "GeneralSequence" - базовым элементом.

<code>
<xs:complexType name="OverallSequence">
  <xs:group  ref="firstItem" />
</xs:complexType></p>

<p><xs:group name="sixthChoice">
  <xs:choice>
    <xs:group  ref="secondItem" />
    <xs:group  ref="thirdItem" />
    <xs:group  ref="fourthItem" />
    <xs:group  ref="fifthItem" />
    <xs:group  ref="sixthItem" />
  </xs:choice>
</xs:group></p>

<p><xs:group name="sixthItem">
  <xs:sequence>
    <xs:element name="X6" type="xs:string" />
    <xs:group    ref="sixthChoice" minOccurs="0" >
  </xs:sequence>
</xs:group></p>

<p><xs:group name="fifthItem">
  <xs:sequence>
    <xs:element name="X5"  type="xs:string" />
    <xs:group    ref="sixthItem" />
  </xs:sequence>
</xs:group></p>

<p><xs:group name="fourthChoice">
  <xs:choice>
    <xs:group  ref="secondItem" />
    <xs:group  ref="thirdItem" />
    <xs:group  ref="fourthItem" />
  </xs:choice>
</xs:group></p>

<p><xs:group name="fourthItem" />
  <xs:sequence>
    <xs:element name="X4" type="xs:string" />
    <xs:group    ref="fourthChoice" minOccurs="0" >
    <xs:group    ref="fifthItem" />
  </xs:sequence>
</xs:group></p>

<p><xs:group name="thirdItem" />
  <xs:sequence>
    <xs:element name="X3" type="xs:string" />
    <xs:group    ref="fourthItem">
  </xs:sequence>
</xs:group></p>

<p><xs:group name="secondItem" />
  <xs:sequence>
    <xs:element name="X2" type="xs:string" />
    <xs:group    ref="thirdItem">
  </xs:sequence>
</xs:group></p>

<p><xs:group name="firstItem" />
  <xs:sequence>
    <xs:element name="X1" type="xs:string" />
    <xs:group    ref="secondItem">
  </xs:sequence>
</xs:group>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...