более чистое расширение элементов с использованием XSD - PullRequest
0 голосов
/ 07 сентября 2010

Я определил XML-схему, которая содержит элемент с именем 'field' и расширение к нему, называемое 'составное поле'. определяется следующим образом:

<xs:complexType name="field">
        <xs:sequence>
            <xs:element name="value" type="xs:string" />
        </xs:sequence>      
</xs:complexType>
<xs:complexType name="composite-Field">
        <xs:complexContent>
          <xs:extension base="field">
            <xs:sequence>
                    <xs:element name="length" type="xs:integer" />
                  </xs:sequence>
                </xs:extension>
        </xs:complexContent>
</xs:complexType>

для того, чтобы использовать его в моем XML, должно быть:

<field xsi:type="composite-Field">
  <value>enjoy</value>
  <length>30</length>
</field>

Я не хочу, чтобы мои пользователи XML использовали синтаксис схемы, такой как xsi: type = ... ""
Поэтому мой вопрос: Есть ли способ сделать синтаксис XML следующим:

<composite-Field>
      <value>enjoy</value>
      <length>30</length>
</composite-Field>

поэтому имя элемента подразумевает его наследование и не заставит пользователей добавлять атрибут типа ??

Я попробовал это:

<xs:element name="MyCompositeField" type="composite-field"/>

и затем:

<MyCompositeField>
          <value>enjoy</value>
          <length>30</length>
</MyCompositeField>

но он также не прошел проверку схемы XSD


12/09/2010: В ответ на предложенный ответ я немного уточнил свой вопрос.
Схема выглядит так:

<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> 

    <xs:element name="general">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="field" type="field" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="field"> 
        <xs:sequence> 
            <xs:element name="value" type="xs:string" /> 
        </xs:sequence> 
    </xs:complexType> 



    <xs:complexType name="composite-Field" > 
        <xs:complexContent> 
            <xs:extension base="field" > 
                <xs:sequence> 
                    <xs:element name="length" type="xs:integer" /> 
                </xs:sequence> 
            </xs:extension> 
        </xs:complexContent> 
    </xs:complexType> 

    <xs:element name="MyCompositeField" type="composite-Field"/> 

</xs:schema> 

и требуемый xml выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
 <general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <MyCompositeField> 
        <value>enjoy</value> 
        <length>30</length> 
    </MyCompositeField> 

 </general>

используя эту комбинацию, я получаю в ответ сообщение об ошибке:

cvc-complex-type.2.4.a: неверно контент был найден начиная с элемент 'MyCompositeField'. Один из '{field}' ожидается.

1 Ответ

1 голос
/ 07 сентября 2010

Обновление вашего вопроса показывает, что настоящая проблема заключается в элементе <general>.Допустимым документом будет

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
    </field> 
</general>

Расширение типа «поле» не изменяет исходный тип.Вместо этого он создает новый тип, основанный на старом типе «поля».Если вы хотите, чтобы оба элемента <value> и <length> были элементами элемента <field>, вам следует изменить тип элемента <field> с «поля» на «составное поле».

<xs:element name="general">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="field" type="composite-Field" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

Это подтверждает документ

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
        <length>30</length> 
    </field> 
</general>

Другое решение состоит в том, чтобы изменить элемент <general>, имеющий дочерний элемент <MyCompositeField> вместо элемента <field>, так как <MyCompositeField> уже имееттип контента "составное поле"

<xs:element name="general">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="MyCompositeField" />
        </xs:sequence>
    </xs:complexType>
</xs:element>

, который будет проверять документ

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema2.xsd">
    <MyCompositeField>
        <value>enjoy</value>
        <length>30</length>
    </MyCompositeField>
</general>

Обновление 2010-08-14

Комментарий автора оригинала:

Но я хочу, чтобы элемент 'general' имел возможность содержать либо 'field', либо 'составное поле'.Не ограничивайтесь наличием ТОЛЬКО одного из этих типов.

Итак, ваша реальная проблема в том, что вы хотите, чтобы ваша схема проверяла оба этих документа?

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
    </field> 
</general>

и

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <MyCompositeField>
        <value>enjoy</value>
        <length>30</length>
    </MyCompositeField>
</general>

В этом случае весь вопрос можно рассматривать как:

  1. "как разрешить элементу иметь один из этих вариантов выбора в качестве дочернего элемента?"
    илипотому что ваши типы почти одинаковы:
  2. «как разрешить необязательный элемент (элемент, который может отсутствовать)?»

Весь вопрос мог бы быть решен намного быстрее, если бы вы имеливначале четко указывалось, какую цель / код вы хотите достичь и какой код у вас есть в настоящее время, что вызывает ваши проблемы

Ответ на # 1 Используйте <xs:choice>, чтобы разрешить один из несколькихнезависимое дочернее содержимое.

С этой структурой вы можете разрешить <general> иметь либо <field>, либо <MyCompositeField> дочерний элемент

<xs:element name="general">
    <xs:complexType>
        <xs:choice>
            <xs:element name="field" type="field" />
            <xs:element name="MyCompositeField" type="composite-Field" />
        </xs:choice>
    </xs:complexType>
</xs:element>

Так что это изменение в вашей схеме позволитдокументы, которые я разместил выше.

Ответ на # 2 Если единственная причина иметь тип composite-Field состоит в том, чтобы допустить дополнительный элемент <length>, вы можете просто легко изменить исходный тип field и использовать его вместо типа composite-Field

<xs:complexType name="field"> 
    <xs:sequence> 
        <xs:element name="value" type="xs:string" /> 
        <xs:element name="length" type="xs:integer" minOccurs="0" /> 
    </xs:sequence> 
</xs:complexType> 

Это определение схемы создает тип, который допускает необязательный элемент длины и, таким образом, проверяет оба этих документа

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
    </field> 
</general>

и

<?xml version="1.0" encoding="UTF-8"?>
<general xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="schema2.xsd">
    <field> 
        <value>enjoy</value> 
        <length>30</length> 
    </field> 
</general>
...