为什么我的JAXB Unmarshaller找不到导入模式中声明的元素?

时间:2010-02-12 14:18:20

标签: java xsd xml-namespaces

我有两个带有循环依赖的模式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" />

我传给Unmarshaller的XSD是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);

有谁能解释我做错了什么?感谢。

1 个答案:

答案 0 :(得分:1)

<xs:import>用于将在其他模式中定义的名称空间导入当前模式。 schemaLocation属性只不过是在哪里找到其他命名空间的提示。

对于B.xsd,您说您要导入名称空间http://blah.org,并且该名称空间由A.xsd中的架构处理。

如果是A.xsd,则导入B.xsd并未指定您要导入的名称空间。

如果A.xsdB.xsd表示不同的命名空间,则import需要明确指定。

另一方面,如果您只是尝试在同一名称空间中内联其他模式文件中的元素,那么include指令更合适。


编辑:好的,看过您的架构片段后,我可以说<xs:import>绝对不是正确的做法。 A.xsdB.xsd都定义了同一命名空间(http://foo.org/A)中的元素,因此您应该使用<xs:include>代替。

当Java遇到<xs:import>,并且该导入的命名空间是它已经知道的命名空间时,它实际上忽略了它。因此,当它解析B.xsd(在命名空间http://foo.org/A中),并且它找到同一命名空间的导入时,它会忽略它。