Ограничение динамического перечисления с использованием XSD 1.1

Я пытаюсь создать определение схемы, используя XSD 1.1, в котором результат одного элемента зависит от другого. Например, у меня есть раскрывающийся список стран и список штатов для каждой страны. Когда человек выбирает страну, могут быть выбраны только штаты этой страны. Псевдокод того, чего я пытаюсь добиться, выглядит примерно так.

<xs:schema xmlns:ie="http://www.interviewexchange.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="country">       
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <xs:enumeration value="USA" />
            <xs:enumeration value="UK" />
            <xs:enumeration value="India" />
        </xs:restriction>
    </xs:simpleType>
</xs:element>
<xs:element name="state">       
    <xs:simpleType>
        <xs:restriction base="xs:string">
            <assert test="if (country eq 'USA')">
            <xs:enumeration value="MA" />
            <xs:enumeration value="AR" />
            <xs:enumeration value="NY" />
            </assert">
            <assert test="if (country eq 'India')">
            <xs:enumeration value="AP" />
            <xs:enumeration value="TN" />
            <xs:enumeration value="MP" />
            </assert">
        </xs:restriction>
    </xs:simpleType>
</xs:element>

Please suggest me whether I am following the right approach, If I am following the right approach, can anyone give me the code of how this restriction can be attained? Thanks in Advance...


person Adithya Puram    schedule 30.11.2012    source источник
comment
Этот вопрос может помочь stackoverflow.com/questions/13308585/   -  person nine9ths    schedule 01.12.2012
comment
Это решение использовало schematron и использовало значения, разделенные запятыми, вместо перечисления. Не могли бы вы предоставить решение, которое использует функции, добавленные в XSD 1.1, такие как «утверждение теста», без использования schematron и использует перечисление вместо значений, разделенных запятыми. Спасибо.   -  person Adithya Puram    schedule 01.12.2012
comment
Извините, я пропустил часть 1.1, я еще не использовал 1.1, но прочитал spec, похоже, что вы не можете использовать утверждения и перечисления вместе, @test — это просто XPATH 2.0, который оценивается в контексте тестируемого элемента.   -  person nine9ths    schedule 01.12.2012


Ответы (1)


Вы приближаетесь.

В XSD 1.1 утверждения могут смотреть в поддерево только вниз, а не вверх или вверх, поэтому, если вы хотите использовать утверждения здесь, вам нужно поместить их не в тип для «состояния», а в тип для «адрес»:

<xs:element name="address">
  <xs:complexType>
    <xs:sequence>
      <xs:element ref="street"/>
      <xs:element ref="city"/>
      <xs:element ref="state" minOccurs="0"/>
      <xs:element ref="country"/>
    </xs:sequence>
    <xs:assert test="(country = 'UK' and not(state))
      or
      (country = 'US' and state = ('MA', 'AR', 'NY'))
      or
      (country = 'IN' and state = ('AP', 'TN', 'MP'))
      "/>
  </xs:complexType>
</xs:element>

Другой подход (также в XSD 1.1) заключается в использовании условного присвоения типа. Это позволяет назначать элементу разные типы на основе выражений XPath, которые могут ссылаться на его элементы (но не на его дочерние элементы). Если мы переместим страну и штат в атрибуты (а затем, для согласованности, также переместим улицу и город в атрибуты), мы могли бы использовать условное присвоение типа таким образом. Во-первых, определим различные простые типы, которые нам нужны для состояния:

<xs:simpleType name="US-states">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="MA" />
    <xs:enumeration value="AR" />
    <xs:enumeration value="NY" />      
  </xs:restriction>
</xs:simpleType>

<xs:simpleType name="IN-states">
  <xs:restriction base="xs:NMTOKEN">
    <xs:enumeration value="AP" />
    <xs:enumeration value="TN" />
    <xs:enumeration value="MP" />   
  </xs:restriction>
</xs:simpleType>

Затем определите три разных сложных типа для трех разных типов адресов, которые нам нужны. Для иллюстрации я предполагаю, что адреса в Великобритании не имеют атрибута «штат».

<xs:complexType name="US-address">
  <xs:attribute name="street" type="xs:string" use="required"/>
  <xs:attribute name="city" type="xs:string" use="required"/>
  <xs:attribute name="state" type="US-states"/>
  <xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="UK-address">
  <xs:attribute name="street" type="xs:string" use="required"/>
  <xs:attribute name="city" type="xs:string" use="required"/>
  <xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>
<xs:complexType name="IN-address">
  <xs:attribute name="street" type="xs:string" use="required"/>
  <xs:attribute name="city" type="xs:string" use="required"/>
  <xs:attribute name="state" type="IN-states"/>
  <xs:attribute name="country" type="xs:NMTOKEN" use="required"/>
</xs:complexType>

Теперь мы привязываем элемент address к правильному из них на основе значения «страны»:

<xs:element name="address">
  <xs:alternative test="@country='US'" type="US-address"/>
  <xs:alternative test="@country='IN'" type="IN-address"/>
  <xs:alternative test="@country='UK'" type="UK-address"/>
  <xs:alternative type="xs:error"/>
</xs:element>

Альтернативы проверяются по порядку, и первая из них, проверка которой дает положительный результат, присваивает тип. Последняя альтернатива (без тестового атрибута) предоставляет значение по умолчанию, которое в данном случае является типом ошибки (никакие элементы или атрибуты не соответствуют типу ошибки).

person C. M. Sperberg-McQueen    schedule 12.12.2012
comment
Если вы хотите ограничить не только пары значений «страна/штат», но и тройки значений «страна/штат/город», проще расширить решение на основе утверждений, чем решение с условным присвоением типов. Расширение утверждения для проверки значений города должно быть очевидным: в дополнение к уже выраженному ограничению вы хотите проверить, что для данной пары страна/штат значения города взяты из определенного набора. Вы можете сделать это, переписав дизъюнкты: (country='US' and state='MA' and city=('Boston', 'Worcester', 'Pittsfield', 'Northhampton','Springfield') or ... - person C. M. Sperberg-McQueen; 13.12.2012
comment
Большое спасибо C. M. Sperberg-McQueen - person Adithya Puram; 13.12.2012
comment
У меня есть к вам последний вопрос: знаете ли вы какие-либо библиотеки Java, которые выполняют проверку XSD 1.1, кроме Saxon (очень дорого)? Я ищу бесплатную версию, и единственная бесплатная реализация — это xercesImpl-2.11.0.jar, которая все еще находится на стадии бета-тестирования. - person Adithya Puram; 13.12.2012
comment
Для XSD 1.1 в настоящее время вы выбираете Saxon и Xerces J. - person C. M. Sperberg-McQueen; 13.12.2012