В XSD 1.0 - Как реализовать выбор xs: внутри xs: all? - PullRequest
0 голосов
/ 18 июня 2019

Я хочу указать схему XML, которая не предписывает порядок, но включает требование выбора. Что считается «наилучшей практикой» для этого?

Например, предположим, что я хочу, чтобы следующие оба действовали:

<foo>
  <bar>3</bar>
  <baz>tree</baz>
  <blort>
    <location>somewhere</location>
    <elevation>2000ft</elevation>
    <zing>1234567</zing>
  </blort>
</foo>

и

<foo>
  <baz>tree</baz>
  <blort>
    <elevation>2000ft</elevation>
    <location>somewhere</location>
    <bling>
      <name>A name</name>
      <number>7</number>
    </bling>
  </blort>
  <bar>3</bar>
</foo>

С общими правилами «английского описания», которые выглядят примерно так: «Вы должны включать столбец, баз и бластер в любом порядке. Бласт должен включать местоположение, высоту и ровно одно из или побрякушки, или звуки, в любом порядке. "

Я хочу разобрать это в проверяющем парсере, который использует XSD 1.0. Моя первая наивная попытка была такой:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema 
    targetNamespace="http://my.url/Foo"
    elementFormDefault="qualified"
    xmlns="http://my.url/Foo"
    xmlns:mstns="http://my.url/Foo"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>

<xs:complexType name="bling">
  <xs:all>
    <xs:element name="name" type="xs:string"/>
    <xs:element name="number" type="xs:decimal"/>
  </xs:all>
</xs:complexType>

<xs:complexType name="blort">
  <xs:all>
    <xs:element name="location" type="xs:string"/>
    <xs:element name="elevation" type="xs:string"/>
    <xs:choice>
      <xs:element name="zing" type="xs:string"/>
      <xs:element name="bling" type="mstns:bling"/>
    </xs:choice>
  </xs:all>
</xs:complexType>


<xs:complexType name="foo">
  <xs:all>
    <xs:element name="bar" type="xs:decimal"/>
    <xs:element name="baz" type="xs:string"/>
    <xs:element name="blort" type="mstns:blort"/>
  </xs:all>
</xs:complexType>

<xs:element name="foo" type="mstns:foo"/>

</xs:schema>

Но, конечно, это не работает. Вы не можете поместить «выбор» в «все».

Мне не удалось найти способ выразить в XSD то, что я ищу.

1 Ответ

1 голос
/ 19 июня 2019

Вы можете использовать подход substitutionGroup .

Это включает в себя замену xs:choice с использованием атрибута substitutionGroup. Таким образом, в вашем случае complexType с именем "bling" необходимо преобразовать в отдельный элемент с именем bling с помощью substitutionGroup distinctIng

<xs:element name="bling" substitutionGroup="distinctIng">
  <xs:complexType>
    <xs:all>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="number" type="xs:decimal"/>
    </xs:all>
  </xs:complexType>
</xs:element>

, чтобы сделать его частью substitutionGroup="distinctIng". Теперь вы можете поместить все остальные (в данном случае: один) элементы в один и тот же substitutionGroup с именем, например, distinctIng:

<xs:element name="distinctIng" />  <!-- abstract base element -->
<xs:element name="zing"  substitutionGroup="distinctIng" type="xs:string" />
<xs:element name="bling" substitutionGroup="distinctIng">
  ... (code from above) ...
</xs:element>

Единственное, что осталось сделать сейчас, это обратиться к базовому элементу с

<xs:element ref="distinctIng" />

, который в этом примере представляет собой целый xs:choice заменяющий код:

<xs:complexType name="blort">
  <xs:all>
    <xs:element name="location" type="xs:string" />
    <xs:element name="elevation" type="xs:string" />
    <xs:element ref ="distinctIng" />  <!-- Replaced xs:choice by the above -->
  </xs:all>
</xs:complexType>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...