Короче говоря, я сомневаюсь: расширяя смешанный тип элемента в XML-схеме W3C, нужно ли нам явно объявлять расширенный элемент? Или это неявно вытекает из того факта, что тип расширенного элемента является смешанным?
Самый простой пример, который мне удалось создать, следующий.
Учитывая следующий файл XML-схемы «foo.xsd»
<?xml version = "1.0" encoding = "utf-8"?>
<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema">
<xs:complexType name = "mixedElement" mixed = "true">
<xs:choice minOccurs = "0" maxOccurs = "unbounded">
<xs:element name = "elem"/>
</xs:choice>
</xs:complexType>
<xs:element name = "root">
<xs:complexType>
<xs:complexContent>
<xs:extension base = "mixedElement"/>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
где элемент mixed = "true
расширяет сложный тип root
(явно mixedElement
), но без mixed = "true"
, и задан следующий тривиальный XML-файл "foo.xml"
<?xml version = "1.0" encoding = "utf-8"?>
<root
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation = "foo.xsd">abc<elem/>xyz</root>
где содержимое элемента mixed = "true"
смешано, мы имеем это в соответствии с root
xmllint --noout --schema foo.xsd foo.xml
«foo.xml» действителен, но, согласно валидатору XML-схемы (библиотека Python), это не так, потому что
File "/usr/lib/python3/dist-packages/xmlschema/validators/schemas.py", line 1678, in validate
raise error
xmlschema.validators.exceptions.XMLSchemaValidationError: failed validating <Element 'root' at 0x7f3592775260> with XsdGroup(model='sequence', occurs=[1, 1]):
Reason: character data between child elements not allowed
«foo.xml» действителен для обоих валидаторов, если я добавляю xmllint
к элементу mixed = "true"
.
<xs:element name = "root" mixed = "true"> <!-- added mixed = "true" -->
Итак, вопрос в том, кто прав в соответствии с рекомендациями W3C XML Schema?
root
, значит, файл "foo.xml" действителен?
Или библиотека Python XML Schema Validator, которая говорит, что это не так?
--- РЕДАКТИРОВАТЬ ---
Как предложил Майкл Кей в своем ответе («Посмотрите, что произойдет, если вы сделаете расширение нетривиальным, добавив некоторое содержимое элемента»), я добавил элемент xmllint
в расширение схемы (новый файл «bar.xsd» )
<?xml version = "1.0" encoding = "utf-8"?>
<xs:schema xmlns:xs = "http://www.w3.org/2001/XMLSchema">
<xs:complexType name = "mixedElement" mixed = "true">
<xs:choice minOccurs = "0" maxOccurs = "unbounded">
<xs:element name = "elem"/>
</xs:choice>
</xs:complexType>
<xs:element name = "root">
<xs:complexType>
<xs:complexContent>
<xs:extension base = "mixedElement">
<xs:choice minOccurs = "0" maxOccurs = "unbounded">
<xs:element name = "elem2"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
и добавил элемент elem2
в файл XML ("bar.xml")
<?xml version = "1.0" encoding = "utf-8"?>
<root
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation = "bar.xsd">abc<elem/>xyz<elem2>123</elem2>abc</root>
Теперь оба валидатора согласны.
XML-файл недействителен согласно elem2
bar.xsd:12: element complexType: Schemas parser error : local complex type: The content type of both, the type and its base type, must either 'mixed' or 'element-only'.
WXS schema bar.xsd failed to compile
а также согласно библиотеке Python
xmlschema.validators.exceptions.XMLSchemaParseError: base has a different content type (mixed=True) and the extension group is not empty:
Читая спецификацию: XML Schema 1.0, часть 1, раздел 3.4.6, подраздел Schema Component Constraint: Derivation Valid (Extension)
, правило 1.4.3.2.2.1 гласит: Оба {типа контента} должны быть смешанными или оба должны быть только элементами.
Это предполагает, что эта схема недействительна.
Однако Saxon-EE (мой процессор схемы) принимает его, и Saxon-EE проходит все тесты на соответствие, что позволяет предположить, что я что-то пропустил.
Теперь, если я изменю производный тип на mixed = "false"
, Saxon все равно примет его, и это, похоже, прямо противоречит только что процитированному правилу 1.4.3.2.2.1. Это наводит меня на мысль, что (а) Саксон ошибается и (б) в наборе тестов W3C нет теста для этого.
Я не вижу в спецификации ничего, что указывало бы на то, что производный тип наследует свойство базового типа.
Кроме того, XSD 1.1 исправляет упущение в XSD 1.0, четко говоря, что если complexType
и его дочерний элемент complexContent
имеют атрибут mixed
, они должны быть согласованными.
Я поднял саксонскую ошибку https://saxonica.plan.io/issues/6523
Обновлять:
Я думаю, что правило XSD, которое фактически нарушает этот пример, — это правило 1.4.3.1 «Ограничение компонента схемы: допустимое деривирование (расширение)». В XSD 1.0 это выражено как {тип контента} определения сложного типа само по себе должно указывать частицу, а в XSD 1.1 более четко это выражается как T.{тип контента}.{разнообразие} = только элемент или смешанный. Правило 1.4 в целом говорит о том, что когда вы получаете сложный тип путем расширения, либо (1.4.1) оба должны иметь простое содержимое, либо (1.4.2) оба должны иметь пустое содержимое, либо (1.4.3) (1.4.3.1) расширение не должно быть пустым и (1.4.3.2) другие условия.
Судя по всему, Saxon не применяет версию 1.4.3.1.
Посмотрите, что произойдет, если вы сделаете расширение нетривиальным, добавив некоторый контент элемента.
Я, кстати, понятия не имею, почему спецификация разрешает пустое расширение пустого типа, но запрещает пустое расширение непустого типа.
Дальнейшее обновление
Хорошо, я начну снова.
Я собираюсь использовать цитаты из XSD 1.1, хотя не думаю, что правила существенно отличаются.
В 3.4.2.3.3 Mapping Rules for Content Type Property of Complex Content
, в «сводке сопоставления», правила для свойства {content type}:
effective mixed
ложно.explicit content
пусто.effective content
пусто.effective content type
является смешанным (то есть фактически наследуется от базового типа; фактически оно говорит, что атрибут mixed
производного типа игнорируется)Таким образом, когда вы определяете тип с пустым расширением, как в этом примере, вы фактически получаете неизмененный базовый тип. Это верно, даже если в производном типе явно указано mixed = "false"
— похоже, это игнорируется (и в саксонском коде есть комментарий, указывающий на это).
Правила, которые я приводил ранее, такие как Rule 1.4.3.2.2.1: Both {content type}s must be mixed or both must be element-only
, применяются только во время проверки компонентов схемы, и для интерпретации этих правил мы должны сначала понять правила построения компонентов схемы. Правило, согласно которому оба типа контента должны быть смешаны, не нарушается, поскольку, как мы только что видели, правила построения компонентов схемы гарантируют, что оба типа контента действительно смешаны, даже если в исходном документе схемы об этом явно не говорится.
Добавил правку в вопрос. Мне кажется, вы поняли суть: при добавлении элемента в расширение и xmllint, и библиотека Python говорят, что XML-файл недействителен. Я сообщу об этой проблеме авторам библиотеки Python. Спасибо за ответ.