Ограничение совместного использования атрибута / элемента в XML-схеме - PullRequest
8 голосов
/ 26 ноября 2008

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

<primitive-list>
    <primitive name="P1">
        <definition><!-- primitive specification --></definition>
    </primitive>
    <primitive name="P2">
        <definition><!-- primitive specification --></definition>
    </primitive>

    <!-- other common primitives are specified here-->

<primitive-list>

<composite-list>
    <composite name="C1">
        <primitive ref="P1" />
        <primitive ref="P2" />
        <primitive>
            <definition><!-- inline primitive specification --></definition>
        </primitive>        
    </composite>

    <!-- Other compisites are specified here-->

</composite-list>

Схема должна подразумевать, что:

  • Если элемент примитив указан внутри элемента примитив-список , то он должен содержать атрибут name и встроенное определение элемент, но не атрибут ref .
  • Если элемент примитив указан в элементе составной , то он должен содержать либо атрибут ref , либо элемент definition, имя не допускается ни в одном из случаев.

Я почти уверен, что это возможно, поскольку элемент element в самой XML-схеме ведет себя именно так. Так что любой, кто обладает этим священным знанием, пожалуйста, поделитесь: -)

Заранее спасибо.

Ответы [ 3 ]

9 голосов
/ 03 декабря 2008

После поиска в Интернете и поиска в некоторых книгах я понял, как это реализовать.

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

<xs:complexType name="primitive" abstract="true">
    <xs:sequence>
        <xs:element ref="definition" minOccurs="0" maxOccurs="unbounded" />
    </xs:sequence>
    <xs:attribute name="name" type="xs:Name" />
    <xs:attribute name="ref" type="xs:Name" />
</xs:complexType>

Затем мы определяем два примитива подтипов, которые будут использоваться в primitive-list , и композит соответственно.

<xs:complexType name="public-primitive">
    <xs:complexContent>
        <xs:restriction base="primitive">
            <xs:sequence>
                <xs:element ref="definition" minOccurs="1" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="name" type="xs:Name" use="required" />
            <xs:attribute name="ref" use="prohibited" />
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="private-primitive">
    <xs:complexContent>
        <xs:restriction base="primitive">
            <xs:sequence>
                <xs:element ref="definition" minOccurs="0" maxOccurs="unbounded" />
            </xs:sequence>
            <xs:attribute name="name" use="prohibited" />
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

Теперь мы можем определить элементы примитива и составные в терминах этих сложных типов следующим образом:

<xs:element name="primitive-list">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="primitive" type="public-primitive" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="composite">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="primitive" type="private-primitive" maxOccurs="unbounded">
                <xs:key name="definition-ref--co-occurrence--constraint">
                    <xs:selector xpath="." />
                    <xs:field xpath="definition|@ref" />
                </xs:key>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Давайте посмотрим на требования исходной схемы и посмотрим, как они применяются:

  • Если элемент примитив указан внутри элемента primitive-list , то он должен содержать атрибут name и внедренное определение элемент, но не атрибут ref .

Это требование обеспечивается определением только публично-примитивного типа .

  • Если элемент примитив указан в элементе составной , то он должен содержать либо атрибут ref , либо элемент definition, имя не допускается ни в одном из случаев.

Это требование обеспечивается определением типа private-primitive и элементом xs: key , указанным в элементе primitive , определенном внутри составной элемент. xs: key гарантирует, что присутствует ref или определение , но не оба.

0 голосов
/ 27 ноября 2008

Хорошо, вот пример, он приближает вас, единственное, что не обрабатывается, - это атрибут примитива и ref в композите. Глядя на то, что я могу найти, кажется почти невозможным сделать это через схему. Хотя я не уверен на 100%, но во всех случаях, когда я видел, что это сделано, такая схема используется для высокоуровневой проверки, а затем код процесса используется для проверки отдельных элементов.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="http://www.iowacomputergurus.com/stackoverflow/samples/xsdexample"
    elementFormDefault="qualified"
    xmlns="http://www.iowacomputergurus.com/stackoverflow/samples/xsdexample"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>

  <xs:complexType name="PrimitiveType">
    <xs:sequence>
      <xs:element name="definition" type="xs:string" minOccurs="1" maxOccurs="1" />
    </xs:sequence>
    <xs:attribute name ="name" use="required" type="xs:string" />
  </xs:complexType>

  <xs:element name="root">
    <xs:complexType>
      <xs:sequence>
          <xs:element name="primitive-list" minOccurs="1" maxOccurs="1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="primitive" type="PrimitiveType" minOccurs="1" maxOccurs="unbounded" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
          <xs:element name="composite-list" minOccurs="1" maxOccurs="1">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="composite">
                  <xs:complexType>
                    <xs:sequence>
                      <xs:element name="primitive" minOccurs="1" maxOccurs="unbounded">
                        <xs:complexType>
                          <xs:sequence>
                            <xs:element name="definition" minOccurs="0" maxOccurs="1" />
                          </xs:sequence>
                          <xs:attribute name="ref" use="optional" type="xs:string" />
                        </xs:complexType>
                      </xs:element>
                    </xs:sequence>
                    <xs:attribute name="name" type="xs:string" use="required" />
                  </xs:complexType>
                </xs:element>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>  
</xs:schema>
0 голосов
/ 26 ноября 2008

Да, это возможно. При создании XML-схемы вы будете создавать сложный тип для каждого сценария в зависимости от того, где в дереве XML определен элемент.

Если у меня появится минутка позже, я могу попытаться привести здесь пример для вас, у меня просто нет времени, чтобы все идеально отформатировать для публикации здесь.

Лично я настоятельно рекомендую посмотреть этот учебник w3schools , поскольку он должен дать вам то, что вам нужно.

...