Путаница с условным назначением типа XSD по умолчанию?

Я пытаюсь создать XSD с CTA. У меня есть следующий XML:

<?xml version="1.0" encoding="UTF-8"?>
<persons xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="test.xsd">
    <person version="1">
        <firstname>toto</firstname>
        <lastname>tutu</lastname>
    </person>
    <person version="2">
        <firstname>toto</firstname>
        <lastname>tutu</lastname>
        <birthdate>2017-12-18</birthdate>
    </person>
</persons>

XSD выглядит так:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
    elementFormDefault="qualified"
    vc:minVersion="1.1"> 

    <xs:complexType name="person_v1">
        <xs:sequence>
            <xs:element name="firstname" type="xs:token"/>
            <xs:element name="lastname" type="xs:token"/>
        </xs:sequence>
        <xs:attribute name="version" type="xs:token" use="required" fixed="1"/>
    </xs:complexType>

    <xs:complexType name="person_v2">
        <xs:sequence>
            <xs:element name="firstname" type="xs:token"/>
            <xs:element name="lastname" type="xs:token"/>
            <xs:element name="birthdate" type="xs:date"/>
        </xs:sequence>
        <xs:attribute name="version" type="xs:token" use="required" fixed="2"/>
    </xs:complexType>

    <xs:element name="person">
        <xs:alternative test="@version=1" type="person_v1"/>        
        <xs:alternative test="@version=2" type="person_v2"/>
    </xs:element>

    <xs:element name="persons">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="person" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

XML проверяется на соответствие XSD, но в XSD:

  1. Если я удаляю атрибут версии, он проверяет,
  2. Если я заменю версию 1 на 3, она подтвердит,
  3. Если я удалю все содержимое человека, оно подтвердится.

В моем XSD чего-то не хватает.


person lovelace63    schedule 18.12.2017    source источник


Ответы (1)


  1. Если я удаляю атрибут версии, он проверяет,

Так и должно быть, потому что, когда нет совпадений xs:alternative тестов, person может быть xs:anyType на Общие правила сопоставления для объявлений элементов.

  1. Если я заменю версию 1 на 3, она подтвердит,

Как и должно по той же причине, что и № 1.

  1. Если я удалю все содержимое человека, оно подтвердится.

Нет, это не так. Возможно, вы на самом деле не связали XML-документ с XSD или случайно объединили эксперимент № 3 с экспериментами № 1 или № 2.

Обновлен XSD

Следующий обновленный XSD указывает тип по умолчанию person, а не xs:anyType, чтобы избежать неожиданностей № 1 и № 2. Обратите внимание, что он также использует расширение для объединения общих частей объявлений person_v1 и person_v2 в person_v и для удовлетворения требования о том, что альтернативные типы должны быть производными от общего базового класса. (Если не указано, это xs:anyType и обычно остается незамеченным.)

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
           elementFormDefault="qualified"
           vc:minVersion="1.1"> 
  <xs:complexType name="person_v">
    <xs:sequence>
      <xs:element name="firstname" type="xs:token"/>
      <xs:element name="lastname" type="xs:token"/>
    </xs:sequence>
    <xs:attribute name="version" type="xs:token" use="required"/>
  </xs:complexType>
  <xs:complexType name="person_v1">
    <xs:complexContent>
      <xs:extension base="person_v"/>
    </xs:complexContent>
  </xs:complexType>
  <xs:complexType name="person_v2">
    <xs:complexContent>
      <xs:extension base="person_v">
        <xs:sequence>
          <xs:element name="birthdate" type="xs:date"/>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>
  <xs:element name="person" type="person_v">
    <xs:alternative test="@version=1" type="person_v1"/>        
    <xs:alternative test="@version=2" type="person_v2"/>
  </xs:element>
  <xs:element name="persons">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="person" maxOccurs="unbounded"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

Обновление: вот обновление для person_v, требующее, чтобы эта версия была 1 или 2, чтобы решить проблему в комментариях:

  <xs:complexType name="person_v">
    <xs:sequence>
      <xs:element name="firstname" type="xs:token"/>
      <xs:element name="lastname" type="xs:token"/>
    </xs:sequence>
    <xs:attribute name="version" use="required">
      <xs:simpleType>
        <xs:restriction base="xs:integer">
          <xs:minInclusive value="1"/>
          <xs:maxInclusive value="2"/>
        </xs:restriction>
      </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
person kjhughes    schedule 18.12.2017
comment
Спасибо за вашу помощь. Я попробовал ваш XSD. Он работает лучше, но все же не так, как ожидалось. Действительно, если я изменяю версию = 1 на версию = 3, она все равно проверяется, но если я изменяю версию 2 на другой номер версии, она не проверяется. - person lovelace63; 18.12.2017
comment
@lovelace63: Это достаточно легко решить, изменив person_v, чтобы ограничить version значением 1 или 2. Ответ обновлен. - person kjhughes; 18.12.2017
comment
Спасибо большое - person lovelace63; 19.12.2017