Почему мой JAXB Unmarshaller не может найти элемент, объявленный в импортированной схеме?

У меня есть две схемы A и B с циклической зависимостью (это промежуточный шаг). XML-файлы, которые я использую в качестве входных данных, проверяются на соответствие схеме в соответствии с xmllint и Visual Studio. Eclipse сообщает мне, что обе схемы содержат два глобальных компонента с одинаковыми именами.

A.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
  targetNamespace="http://foo.org/A"
  xmlns="http://foo.org/A"
  elementFormDefault="unqualified"
  attributeFormDefault="unqualified">

<xs:import schemaLocation="b.xsd" />

B.xsd:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
  xmlns:foo="http://foo.org/A"
  elementFormDefault="unqualified"
  attributeFormDefault="unqualified">

  <xs:import namespace="http://foo.org/A" schemaLocation="a.xsd" />

XSD, который я передаю Unmarshaller, — это A.xsd. Когда он встречает элемент, определенный в B.xsd, он жалуется:

org.xml.sax.SAXParseException: cvc-elt.1: не удается найти объявление элемента «foo».

Я установил схему через (псевдо):

InputStream in = .. A.xsd
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
return factory.newSchema(new StreamSource(in);

Кто-нибудь может объяснить, что я делаю неправильно? Спасибо.


person Elliot    schedule 12.02.2010    source источник


Ответы (1)


<xs:import> используется для импорта пространств имен, определенных в другой схеме, в текущую схему. Атрибут schemaLocation — не что иное, как подсказка, где найти это другое пространство имен.

В случае B.xsd вы говорите, что хотите импортировать пространство имен http://blah.org и что это пространство имен обрабатывается схемой в A.xsd.

В случае A.xsd ваш импорт B.xsd не указывает, какое пространство имен вы импортируете.

Если A.xsd и B.xsd представляют разные пространства имен, то import необходимо указать это явно.

Если, с другой стороны, вы просто пытаетесь встроить элементы из другого файла схемы в том же пространстве имен, то более подходящей будет директива include.


редактировать: Хорошо, увидев фрагменты вашей схемы, я могу сказать, что <xs:import> определенно не подходит. И A.xsd, и B.xsd являются определяющими элементами в одном и том же пространстве имен (http://foo.org/A), поэтому вместо них следует использовать <xs:include>.

Когда Java встречает <xs:import>, а пространство имен этого импорта является пространством имен, о котором ей уже известно, она фактически игнорирует его. Так как он анализирует B.xsd (в пространстве имен http://foo.org/A) и находит импорт для того же самого пространства имен, он его игнорирует.

person skaffman    schedule 12.02.2010
comment
Спасибо за ответ. Я добавил деталей к своему вопросу, показав, как определяются мои элементы ‹xs:schema›. - person Elliot; 12.02.2010