XSD循环导入

Syd*_*ney 4 java xsd xsom

我需要解析一个XSD,XSOM但这个XSD包含循环导入.

A.xsd

<xs:schema xmlns=”ns1” targetNamespace=”ns1”>
  <xs:import namespace=”ns2” schemaLocation=”B.xsd”/>
  <xs:element name=”MyElement” type=”xs:string”/>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

B.xsd

<xs:schema xmlns=”ns2” targetNamespace=”ns2” xmlns:ns1=”ns1”>
  <xs:import namespace=”ns1” schemaLocation=”A.xsd”/>
  <xs:complexType name="MyComplex">
    <xs:sequence>
      <xs:element ref="ns1:MyElement" minOccurs="0"/>
    <xs:sequence>
  <xs:complexType>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

XSOM无法解析模式,因为它检测到由于循环导入而已定义的元素.所以我试图通过外化由A定义并在B中使用的元素来打破循环导入.

C.xsd包含A使用的元素B.请注意,这些元素不在A中使用.不要问我为什么在A中定义了这些元素.

<xs:schema xmlns=”ns1” targetNamespace=”ns1”>
  <xs:element name=”MyElement” type=”xs:string”/>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

A.xsd成了

<xs:schema xmlns=”ns1” targetNamespace=”ns1”>
  <xs:import namespace=”ns2” schemaLocation=”B.xsd”/>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

B.xsd(导入C.xsd而不是A.xsd)成为

<xs:schema xmlns=”ns2” targetNamespace=”ns2” xmlns:ns1=”ns1”>
  <xs:import namespace=”ns1” schemaLocation=”C.xsd”/>
  <xs:complexType name="MyComplex">
    <xs:sequence>
      <xs:element ref="ns1:MyElement" minOccurs="0"/>
    <xs:sequence>
  <xs:complexType>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

XSOM可以解析XSD.但现在我无法使用以下代码创建架构:

SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
sf.setResourceResolver(new MyResourceResolver());
Run Code Online (Sandbox Code Playgroud)

我使用与JDK 1.7捆绑在一起的标准实现.我得到了例外:

src-resolve: Cannot resolve the name 'ns1:MyElement' to a(n) 'element declaration' component.
Run Code Online (Sandbox Code Playgroud)

问题是资源解析器是为B命名空间调用的,而不是为有意义的A命名空间调用的.由于命名空间A由A.xsd和C.xsd共享,因此资源解析器无法找到C.xsd中定义的元素.

循环进口是否有效?是否有可能打破循环导入,以便它可以被解析XSOM,然后由SchemaFactory

C. *_*een 7

关于一般问题:

你问"圆形进口是否有效?" 如果通过循环,则表示存在一系列模式文档S [1],S [2],...,S [n],其中模式文档S [1]按名称引用模式文档S [2],S [2]到S [3],...... S [n-1]到S [n],S [n]到S [1]那么我不相信XSD 1.0规范或XSD 1.1说清楚这样或那样的.(一些工作组成员试图说服工作组提高其对此及相关主题的思路清晰度,但失败了.)有些实现支持循环导入(和其他形式的循环),但我不认为有可能争论从规范,您的实现做错了什么.

另一方面,如果你的意思是只有一个循环使得0 <= i <= n-1,S [i]导入S [i + 1]的命名空间而S [n]导入S的命名空间[1],那么我相信这样的周期显然是合法的(在某些情况下是不可避免的).

我推荐的解决方法是:

  1. 在任何声明任何内容的模式文档中,根据需要使用xs:import,但不要在导入时指定模式位置.这些参考文献中的循环是无害的.
  2. 在调用模式处理器时,请为其提供您希望其读取的所有模式文档的完整列表,如果可能,请通过选项或配置告诉它不要读取任何其他模式文档.
  3. 如果您的模式文档在验证时不接受多个模式文档作为输入,那么您必须有一个模式文档引用您想要读取的所有内容,或者如果您不相信自己将模式文档列表正确在调用时,然后添加一个顶级驱动程序文档,该文档除了包含和导入您要读取的其他模式文档外,不会执行任何操作,具有特定的模式位置信息.

在您的情况下,这意味着从(原始形式)A.xsd和B.xsd中删除xs:import/@ schemaLocation属性,并添加表单的驱动程序文档

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:import namespace="ns1" schemaLocation="A.xsd"/>
  <xs:import namespace="ns2" schemaLocation="B.xsd"/>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

其结果是确保模式文档中对其他模式文档的引用永远不会出现循环; 这消除了一大类XSD实现彼此不一致的情况(在某些情况下它们本身 - 当调用以不同的顺序命名输入时,有时相同的处理器会在相同的输入上产生截然不同的结果).

关于具体问题:

在您的示例中,不要求A.xsd或C.xsd导入ns2,因为它们都不包含对命名空间ns2中的任何组件的任何引用.所以你的例子中的循环似乎是无偿的.

在第二个示例中,您将提供一些未能成功加载架构的代码.但我在该代码中没有看到任何特定模式文档的引用; 除非有相关内容你没有向我们展示,否则验证器无法找到{ns1} MyElement的声明.