Ограничение схемы XML для сложных типов: полное переопределение?

При добавлении ограничений на complexTypes в XML-схемах необходимо ли переписать все элементы, используемые в определении complexType? Если да, почему он не может просто повторно использовать существующие определения элементов и перезаписать новые ограниченные?

Например, ниже; Когда я просто хочу ограничить страну поля, должен ли я снова переписать все 3 поля?

<xs:complexType name="customer">
  <xs:sequence>
    <xs:element name="firstname" type="xs:string"/>
    <xs:element name="lastname" type="xs:string"/>
    <xs:element name="country" type="xs:string"/>
  </xs:sequence>
</xs:complexType>

<xs:complexType name="Norwegian_customer">
  <xs:complexContent>
    <xs:restriction base="customer">
      <xs:sequence>
        <xs:element name="firstname" type="xs:string"/>
        <xs:element name="lastname" type="xs:string"/>
        <xs:element name="country" type="xs:string" fixed="Norway"/>
      </xs:sequence>
    </xs:restriction>
  </xs:complexContent>
</xs:complexType> 

Итак, из приведенного ниже ответа видно, почему мы должны переписать весь тип.

Следующий вопрос

Что такое использование этой функции ограничения?

Одна ситуация, о которой я могу думать; когда вам нужно проверить экземпляры документов, содержащих ограниченные типы, вместо базовых типов в схеме xml.

Скажем, если "B" является базовым типом и его ограничивается "B *". Любой экземплярный документ, содержащий "B *" в том месте, где ожидается элемент документа "B", будет работать. Нам не пришлось бы писать отдельные правила для каждого ограниченного типа. (Атрибут "xsi: type" in документ экземпляра будет проверять его с правильным типом.) Правильно?

Любое другое использование этой функции?

Ответ 1

Ваш первый вопрос: "При добавлении ограничений на complexTypes в XML-схемах необходимо ли переписать все элементы, используемые в определении complexType?" Нет, только те, которые вы хотите включить в определение ограниченного типа. Но да, все те, которые должны быть частью ограничения. Модель контента в ограничении должна стоять сама по себе как полное определение модели контента типа. (С другой стороны, нет необходимости указывать все атрибуты, они наследуются без изменений, если не указано иное.)

Второй вопрос: "Почему он не может просто повторно использовать существующие определения элементов и перезаписать новые ограниченные?" Это разумный вопрос. Ответ несколько сложный: рассмотрим две произвольные модели содержимого E и F. Теперь мы хотим интерпретировать F как ограничение E, в котором упоминаются только элементы и модельные группы в E, которые мы хотим изменить, и опускает любое упоминание элементов и группы моделей, которые мы хотим в одиночку. Является ли эта проблема разрешимой, в общем случае? Гарантировано ли уникальное решение? Может показаться вам очевидным, что в обоих случаях ответ да, но дизайнеры XSD в то время не казались очевидными, и сегодня это не кажется мне очевидным.

Например, пусть E будет

(a+, b+, c*){2}, (a+, b*, c+){3}

и пусть F есть

a{3,4}

Если предположить, что все в F является ограничением чего-либо в E, а все остальное в E следует оставить в покое, то F означает, что мы хотим ограничить E на

(a{3,4}, b+, c*){2}, (a+, b*, c+)

или

(a+, b+, c*){2}, (a{3,4}, b*, c+)

?

Добавление

@nikel запрашивает пример XSD. Приведенный выше пример уже является примером XSD, поэтому я предполагаю, что подразумевается "пример в синтаксисе XSD". Я беру предложение, чтобы этот синтаксис, как показано ниже, должен работать. Сначала мы имеем базовый тип, E:

<xs:complexType name="E">
  <xs:sequence>
    <xs:sequence minOccurs="2" maxOccurs="2">
      <xs:element ref="a" maxOccurs="unbounded"/>
      <xs:element ref="b" maxOccurs="unbounded"/>
      <xs:element ref="c" minOccurs="0" 
                          maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:sequence minOccurs="3" maxOccurs="3">
      <xs:element ref="a" maxOccurs="unbounded"/>
      <xs:element ref="b" minOccurs="0" 
                          maxOccurs="unbounded"/>
      <xs:element ref="c" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:sequence>
</xs:complexType>

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

<xs:complexType name="F">
  <xs:complexContent>
    <xs:restriction base="tns:E">
      <xs:sequence>
        <xs:element ref="a" minOccurs="3" maxOccurs="4"/>          
      </xs:sequence>        
    </xs:restriction>
  </xs:complexContent>
</xs:complexType>

Какова должна быть эффективная модель содержания F?

Последующий вопрос

Вы спрашиваете, по сути, "в этом случае, какое использование ограничения?"

Разумный вопрос. Ответ, который вы предлагаете, является хорошим. В более общем плане, иногда мы считаем полезным знать, что каждый экземпляр типа B * будет экземпляром типа B; деривация посредством ограничения в XSD предназначена для гарантии того, что инвариант. Иногда бывает полезно определить абстрактный тип с двумя или более конкретными ограничениями; что помогает гарантировать, что различные конкретные реализации абстрактного базового типа хорошо связаны друг с другом, даже если ни один из них не является подмножеством или надмножеством любого другого.

Может существовать (нет: есть много) способов, чтобы деривация посредством ограничения могла быть более понятной, простой и удобной в XSD; не нужно было повторять всю модель контента, было бы одним из них. Но тогда это верно для почти всего в XSD. Его единственная реальная добродетель заключается в том, что она поддерживается множеством инструментов, которые многие люди хотят использовать.