Одно пространство имен xml равно одному и только одному файлу схемы?
... или Почему эти файлы проверяются в Visual Studio 2010, но не с xmllint 1?
В настоящее время я работаю против опубликованной схемы xml, где оригинальная привычка автора состоит в том, чтобы разбивать схемы на несколько .xsd файлов, но где некоторые файлы схемы имеют одинаковый targetNamespace
. Действительно ли это разрешено?
Пример (очень упрощенный):
File targetNamespace Contents
------------------------------------------------------------
b1.xsd uri:tempuri.org:b complex type "fooType"
b2.xsd uri:tempuri.org:b simple type "barType"
a.xsd uri:tempuri.org:a imports b1.xsd and b2.xsd
definition of root element "foo", that
extends "b:fooType" with an attribute
of "b:barType"
(Полное содержимое файла ниже.)
Затем у меня есть xml файл, data.xml
, с этим контентом:
<?xml version="1.0"?>
<foo bar="1" xmlns="uri:tempuri.org:a" xmlns:xs="http://www.w3.org/2001/XMLSchema" />
Долгое время я считал, что все это было правильно, поскольку Visual Studio, по-видимому, допускает этот стиль схемы. Однако сегодня я решил настроить утилиту командной строки для проверки файлов xml, и я выбрал xmllint
.
Когда я запустил xmllint --schema a.xsd data.xml
, мне было предложено следующее предупреждение:
a.xsd: 4: импорт элемента: предупреждение синтаксического анализа схемы: элемент '{http://www.w3.org/2001/XMLSchema} import': Пропуск импорта схемы, расположенной на 'b2.xsd' для пространства имен 'uri: tempuri.org: b', поскольку это пространство имен уже было импортировано с помощью схемы, расположенной в 'b1.xsd'.
Тот факт, что импорт b2.xsd
был пропущен, явно приводит к этой ошибке:
a.xsd: 9: атрибут элемента: ошибка парсера схемы: атрибут decl. 'bar', атрибут 'type': Значение QName '{uri: tempuri.org: b} barType' не разрешает определение (n) простого типа.
Если xmllint
верна, в опубликованных спецификациях, с которыми я работаю, будет ошибка. Здесь? И Visual Studio ошибается. Это?
Я понимаю разницу между xs:import
и xs:include
. Прямо сейчас, я просто не понимаю, как xs:include
может исправить ситуацию, поскольку:
-
b1.xsd
и b2.xsd
имеют одинаковые targetNamespace
- оба они отличаются
targetNamespace
от a.xsd
- и они (не должны) знать друг о друге
Является ли это недостатком в исходной спецификации схемы? Я начинаю думать, что третья точка провала имеет решающее значение. Если тот факт, что они не знают друг о друге, привели к их размещению в разных пространствах имен?
b1.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="uri:tempuri.org:b" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="fooType" />
</xs:schema>
b2.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="uri:tempuri.org:b" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="barType">
<xs:restriction base="xs:integer" />
</xs:simpleType>
</xs:schema>
a.xsd:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema targetNamespace="uri:tempuri.org:a" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:b="uri:tempuri.org:b">
<xs:import namespace="uri:tempuri.org:b" schemaLocation="b1.xsd" />
<xs:import namespace="uri:tempuri.org:b" schemaLocation="b2.xsd" />
<xs:element name="foo">
<xs:complexType>
<xs:complexContent>
<xs:extension base="b:fooType">
<xs:attribute name="bar" type="b:barType" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
Примечания:
1) Я использую порт Windows libxml2/xmllint, найденный в www.zlatkovic.com.
Ответы
Ответ 1
Суть проблемы здесь в том, что это значит, когда у вас есть два разных элемента <import>
, когда они оба относятся к одному и тому же пространству имен.
Это помогает прояснить смысл, если учесть, что атрибут schemaLocation
<import>
полностью необязателен. Когда вы оставите это, вы просто говорите: "Я хочу импортировать схему пространства имен XYZ в эту схему". schemaLocation
- это просто намек на то, где найти определение этой другой схемы.
Точный смысл <import>
немного нечеткий, когда вы читаете спецификацию W3C, возможно, намеренно. В результате интерпретации различаются.
Некоторые процессоры XML допускают множественные <import>
для одного и того же пространства имен и по существу объединяют все schemaLocation
в одну цель.
Другие процессоры более строгие и принимают решение о том, что допустимо только одно <import>
для целевого пространства имен. Я думаю, что это более правильно, если вы считаете, что schemaLocation
не является обязательным.
В дополнение к примерам VS и xmllint, которые вы указали, Xerces-J также является супер-строгим и игнорирует последующий <import>
для одного и того же пространства имен задач, что дает ту же ошибку, что и xmllint. XML Spy, с другой стороны, гораздо более разрешительный (но тогда, проверка шпиона XML, как известно, flaky)
Чтобы быть в безопасности, у вас не должно быть этих нескольких импортных товаров. Для данного пространства имен должен быть один "главный" документ, который, в свою очередь, имеет <include>
для каждого поддокумента. Этот мастер часто очень искусственен, действует только как контейнер. для этих поддокументов.
Из того, что я видел, это обычно состоит из "лучшей практики" для XML-схемы, когда дело доходит до максимальной совместимости с инструментами, но некоторые будут утверждать, что это взлом, который отнимает элегантный дизайн схемы.
Мех.