我有两个带有循环依赖的模式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);
有谁能解释我做错了什么?感谢。
答案 0 :(得分: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
中),并且它找到同一命名空间的导入时,它会忽略它。