我有两个具有循环依赖性的模式 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: Cannot find declaration of element 'foo'.
我已经通过(伪)设置了模式:
InputStream in = .. A.xsd
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
return factory.newSchema(new StreamSource(in);
谁能解释我做错了什么?谢谢。
最佳答案
<xs:import>
用于将其他模式中定义的命名空间导入当前模式。 schemaLocation
属性只不过是关于在哪里可以找到其他 namespace 的提示。
在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>
时,并且该导入的 namespace 是它已经知道的 namespace ,然后它实际上忽略了它。因此在解析 B.xsd
时(在命名空间 http://foo.org/A
中),并且它找到了同一命名空间的导入,并忽略了它。
关于java - 为什么我的 JAXB Unmarshaller 找不到在导入模式中声明的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2252337/