XML-схема: почему не может быть xs: у всех есть выбор детей? и как это можно обойти?

17

Я пытаюсь создать схему для элемента <property> , который должен иметь подэлемент <key> и один из <val> , <shell> или <perl> и необязательный <os> или <condition> , а порядок подэлементов не имеет значения.

Вот пример для действительных <property> элементов:

<property>
  <key>A</key>
  <val>b</val>
</property>

<property>
  <key>A</key>
  <val>b</val>
  <os>Windows</os>
</property>

<property>
  <condition>a == 1</condition>
  <key>A</key>
  <perl>1+1</perl>
  <os>unix</os>
</property>

В идеале я думал об использовании <xs:all> для этого:

<xs:element name="property">
  <xs:complexType>
    <xs:all>
      <xs:element name="key" type="xs:string" />
      <xs:choice>
        <xs:element name="val" type="xs:string" />
        <xs:element name="perl" type="xs:string" />
        <xs:element name="shell" type="xs:string" />
      </xs:choice>
      <xs:element name="os" type="xs:string" minOccurs="0" />
      <xs:element name="condition" type="xs:string" minOccurs="0" />
    </xs:all>
  </xs:complexType>
</xs:element>

Но я выяснил, что <xs:all> может содержать только <xs:element> , а не <xs:choice> . Может кто-нибудь объяснить, почему?

Что еще более важно, может ли кто-нибудь предоставить способ проверки такого элемента <property> ?

Я могу поместить три элемента - <val> , <perl> и <shell> - в качестве необязательных элементов в <xs:all> , но я хочу, чтобы схема проверяла, что одна и только одна из трех существует в элементе , Это можно сделать?

    
задан splintor 23.04.2009 в 10:42
источник
  • @splintor: Вы действительно посмотрели окно предварительного просмотра при написании своего вопроса? Я имею в виду, что половина из них была невидимой ... –  Tomalak 23.04.2009 в 11:23
  • Вы имеете в виду, что оба параметра os и condition могут встречаться внутри одного и того же элемента собственности или того или другого или не могут возникнуть? –  Nic Gibson 23.04.2009 в 11:45
  • @Tomalak: Нет. Я пропустил это окно предварительного просмотра. Большое спасибо за его редактирование, чтобы это означало то, что я хотел. –  splintor 23.04.2009 в 12:11
  • @newt: Я имею в виду, что os и условие могут возникать внутри одного и того же элемента свойства или только одного из них или ни одного. Оба они являются opitonal, и они не являются взаимными эксклюзивными. –  splintor 23.04.2009 в 12:13
  • @splintor: ОК. Просто проверяю. У меня такое чувство, что ваша потребность в отсутствии заказа может сделать это очень сложно выразить в xsd. Он может быть разрешимым с использованием групп замещения, но я не уверен. –  Nic Gibson 23.04.2009 в 12:24
Показать остальные комментарии

2 ответа

22

Я думаю, что это немного лучше, поскольку «выбор» теперь является его собственным элементом (typeFacet), но не может использоваться напрямую, поскольку он является абстрактным.

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="property">
    <xs:complexType>
      <xs:all>
        <xs:element name="key" type="xs:string" />
        <xs:element ref="typeFacet" />
        <xs:element name="os" type="xs:string" minOccurs="0" />
        <xs:element name="condition" type="xs:string" minOccurs="0" />
      </xs:all>
    </xs:complexType>
  </xs:element>

  <xs:element name="typeFacet" abstract="true" />
  <xs:element name="val" type="xs:string"   substitutionGroup="typeFacet" />
  <xs:element name="perl" type="xs:string" substitutionGroup="typeFacet" />
  <xs:element name="shell" type="xs:string" substitutionGroup="typeFacet" />
</xs:schema>
    
ответ дан Adam Hawkes 23.04.2009 в 15:38
  • yep, это улучшение. –  13ren 23.04.2009 в 16:07
  • Да, это очень хорошо, что я имел в виду, но был слишком встречен, чтобы на самом деле это сделать. Абстракция, безусловно, тоже хорошая идея. –  Nic Gibson 23.04.2009 в 16:57
  • Отлично, я не знал о замене в схеме XSD. Кажется, это делает то, что мне нужно. Благодарю. –  splintor 23.04.2009 в 21:23
  • Ницца. Это также работает, если val и perl имеют разные типы. –  Igor Nazarenko 28.02.2013 в 17:39
6

Основываясь на комментарии ньюта об использовании подстановочных групп для выбора (протестированных с помощью xmllint):

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="property">
    <xs:complexType>
      <xs:all>
        <xs:element name="key" type="xs:string" />
        <xs:element ref="val"/>
        <xs:element name="os" type="xs:string" minOccurs="0" />
        <xs:element name="condition" type="xs:string" minOccurs="0" />
      </xs:all>
    </xs:complexType>
  </xs:element>

  <xs:element name="val" type="xs:string"/>
  <xs:element name="perl" type="xs:string" substitutionGroup="val" />
  <xs:element name="shell" type="xs:string"  substitutionGroup="val" />
</xs:schema>
    
ответ дан 13ren 23.04.2009 в 15:16
  • Отлично, я не знал о замене в схеме XSD. Кажется, это делает то, что мне нужно. Благодарю. –  splintor 23.04.2009 в 21:24