Как группировать типы и подтипы в XSD - PullRequest
4 голосов
/ 11 июля 2011

У меня есть XML как это:

<type>
    <mainType>...</mainType>
    <subtype>...<subtype>
</type>

Основными типами являются запрещенные строки xs: (их список). И у каждого mainType есть список возможных подтипов. IE:
mainTypeA имеет возможные подтипы: subtype1, subtype2, subtype3
mainTypeB имеет возможные подтипы: subtype4, subtype5

Как я могу представить это в XSD, чтобы каждое из перечислений подтипа было связано конкретно с их основным типом? Есть ли лучший способ представить эти 2 поля, чтобы упростить XSD? Я не против изменения структуры документа XML.

Ответы [ 4 ]

6 голосов
/ 12 июля 2011

(Это был бы дополнительный комментарий в ответе @hugh jadick, но он был слишком длинным для такого.)

У вас есть две проблемы в вашем первоначальном дизайне, которые усложняют структуру:

  1. у вас есть что-то, что можно рассматривать как ограничение совместного вхождения, потому что <subType> может появляться только тогда, когда присутствует <mainType>
  2. объявления элементов несовместимы, поскольку у вас есть
    • ...в том же контексте (дочерние элементы <type>)
    • ... элементов с одинаковыми именами (<mainType>)
    • ... но с другим типом (другое значение и связанные <subType>элементы).

В XML Schema 1.0 не существует общего метода, позволяющего реализовать эти функции, хотя они могут быть достигнуты в некоторых случаях и / или с помощью некоторых методов.Одним из возможных способов решения проблемы неоднозначного типа является использование атрибута xsi:type в документе экземпляра для определения используемого типа схемы (пример 1).

Вместо того, чтобы использовать некоторые возможные обходные пути для решения этих проблем, я предлагаю вам следовать @ 1027 * answer @hugh jadick и создавать элементы с разными именами для всех основных типов, которые также будут иметь разные элементы дляразные подтипы.Если вам не нравится иметь имя типа в качестве имени элемента (или оно недопустимо для имени элемента XML), вы можете поместить его в атрибут, возможно, используя значение по умолчанию или фиксированное значение (<myType1 typeName="Type 1 name">) (Пример 2).Если подтипы являются взаимоисключающими, вы также можете поместить их в атрибут (<myType1 subType="subType2">).Если вы действительно хотите иметь имя типа в содержимом элемента (<mainType1>Type 1 name</mainType1>), то, вероятно, лучше иметь элементы <subType> в качестве следующих братьев и сестер, а не потомков <mainType1>, потому что это приведет к смешанному содержимому, которое легковызывает проблемы, связанные с пробелами и позицией текстового узла (пример 3).

Да, группы подстановки также могут использоваться с ответом @hugh jadick.У вас будет абстрактный элемент <mainType>, и все определения элементов основного типа будут иметь атрибут substitutionGroup="mainType".Вы по-прежнему должны иметь разные имена для разных элементов основного типа, потому что они допускают различный набор разрешенных элементов / значений.Тип этих элементов должен быть получен из типа абстрактного <mainType> элемента, который они заменяют (Пример 4).

Примеры кода

Пример 1

<xs:element name="type">
    <xs:complexType>
        <xs:choice>
            <xs:element name="mainType" type="mainType1"/>
            <xs:element name="mainType" type="mainType2"/>
            <xs:element name="mainType" type="mainType3"/>
        </xs:choice>
    </xs:complexType>
</xs:element>

<type>
    <mainType xsi:type="mainType1"/>
</type>

Пример 2

<xs:element name="mainType1">
    <xs:complexType>
        <xs:choice>
            <xs:element ref="subType1"/>
            <xs:element ref="subType2"/>
            <xs:element ref="subType3"/>
        </xs:choice>
        <xs:attribute name="typeName" type="xs:string"/>
    </xs:complexType>
</xs:element>

Пример 3

<xs:element name="type">
    <xs:complexType>
        <xs:choice>
            <xs:sequence>
                <xs:element name="mainType" type="mainType1"/>
                <xs:choice>
                    <xs:element ref="subType1"/>
                    <xs:element ref="subType2"/>
                    <xs:element ref="subType3"/>
                </xs:choice>
            </xs:sequence>
            <!-- repeat similarily for other main types -->
            <xs:sequence>
                <!-- ... -->
            </xs:sequence>
        </xs:choice>
    </xs:complexType>
</xs:element>

Пример 4

<xs:element name="type">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="mainType"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

<xs:element name="mainType" type="mainType" abstract="true"/>
<xs:element name="mainType1" type="typeForMainType1" substitutionGroup="mainType"/>
<xs:element name="mainType2" type="typeForMainType2" substitutionGroup="mainType"/>

<xs:complexType name="mainType">
<!-- definition for mainType -->
</xs:complexType>

<xs:complexType name="typeForMainType1">
    <xs:complexContent>
        <xs:restriction base="mainType">
            <!-- definition for mainType1 -->
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="typeForMainType2">
    <xs:complexContent>
        <xs:restriction base="mainType">
            <!-- definition for mainType1 -->
        </xs:restriction>
    </xs:complexContent>
</xs:complexType>
3 голосов
/ 11 июля 2011

Вам необходимо явно определить ваш тип как содержащий основной тип и подтип. На каждом этапе вы четко определяете, что возможно в этот момент:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="root">
    <xs:complexType>
      <xs:choice>
        <xs:element name="MyType1" type="MyType1Type" />
        <xs:element name="MyType2" type="MyType2Type" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <!-- MainType definitiions -->
  <xs:complexType name="MyType1Type>
    <xs:all minOccurs="1">
      <xs:element name="MyType1SubType1" type="MyType1SubType1Type" />
      <xs:element name="MyType1SubType2" type="MyType1SubType2Type" />
      <xs:element name="MyType1SubType3" type="MyType1SubType3Type" />
    </xs:all>
  </xs:complexType>
  <xs:complexType name="MyType2Type>
    <xs:all minOccurs="1">
      <xs:element name="MyType2SubType4" type="MyType2SubType4Type" />
      <xs:element name="MyType2SubType5" type="MyType2SubType5Type" />
    </xs:all>
  </xs:complexType>
  <!-- SubType definitions -->
  <xs:complexType name="MyType1SubType1Type>
    <xs:sequence>
      <xs:element name="MyType1SubType1TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType1SubType2Type>
    <xs:sequence>
      <xs:element name="MyType1SubType2TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType1SubType3Type>
    <xs:sequence>
      <xs:element name="MyType1SubType3TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType2SubType4Type>
    <xs:sequence>
      <xs:element name="MyType2SubType4TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="MyType2SubType5Type>
    <xs:sequence>
      <xs:element name="MyType2SubType5TypeValue" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

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

0 голосов
/ 11 июля 2011
<type>
    <name>MainTypeA</name>
    <type>
        <name>subtype1</name>
    </type>
    <type>
        <name>subtype1</name>
    </type>
</type>

или

<type name="MainTypeA">
    ...
    <type name="subtype1">
        ...
    </type>
    <type name="subtype2">
        ...
    </type>
</type>

Это позволяет использовать подтип и т. Д. Бесконечно. Подтипы по своей сути отличаются от типов? Если нет, то нет необходимости создавать отдельный тег subType для них. Единое имя тега для всех типов на любой глубине облегчит анализ.

0 голосов
/ 11 июля 2011

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

<types>
   <type name="mainTypeA">
       <subType name="subType1"></subType>
       <subType name="subType2"></subType>
       <subType name="subType3"></subType>
   </type>
   <type name="mainTypeB">
       <subType name="subType4"></subType>
       <subType name="subType5"></subType>
       <subType name="subType6"></subType>
   </type>
</types>

Другое предложение:

<type name="MainTypeA">
    <type name="subType1"></type>
    <type name="subtype2"></type>
</type>
<type name="MainTypeB">
    <type name="subType3">
        <type name="subSubType1"></type>
    </type>
    <type name="subtype4"></type>
</type>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...