【问题标题】:Dynamic XML Schema Validates Subsection of Document动态 XML 模式验证文档的子部分
【发布时间】:2018-03-08 14:03:06
【问题描述】:

我的情况类似于“XSD with elements from other namespace”,我有 2 个 XML。

一个 XML 片段充当另一个 XML 的包装器。在一个简单的例子中——我们有一个 MESSAGES 包装器,至少包含一个 MESSAGE 元素。每个 MESSAGE 元素都包含一个针对 XSD 进行验证的 PAYLOAD。

给定 MESSAGES 父级中的每个 PAYLOAD 都将针对同一个 XSD 进行验证。但是,不同的 MESSAGES 可以包含针对整个 XSD 主机进行验证的 PAYLOAD。我确实有数百个 XSD 来验证不同类型的 PAYLOAD。

我想拥有自己的 XSD 来验证 MESSAGES 包装器的结构,然后将验证 PAYLOAD 的责任移交给我拥有的众多库存 XSD 之一,具体取决于 PAYLOAD 类型。

重要的一点是我们不能将 PAYLOAD XSD 导入到 MESSAGE XSD - 因为 PAYLOAD 模式类型在 XSD 级别不是固定的。但它是固定在 XML 级别的。

<MESSAGES>
    <MESSAGE>
         <RECIPIENT>Foo</RECIPIENT>
         <PAYLOAD>
              <!-- Large message containing many possible elements -->
         </PAYLOAD>
    <MESSAGE>
    <MESSAGE>
         <RECIPIENT>Bar</RECIPIENT>
         <PAYLOAD>
              <!-- Large message containing many possible elements -->
         </PAYLOAD>
    <MESSAGE>
</MESSAGES>

到目前为止,我注意到了两件事。如果我在父 MESSAGES 级别不提供架构,我可以在 PAYLOAD 级别提供架构,这将正确验证 PAYLOAD。但是,没有验证包装器。

<MESSAGES>
     <MESSAGE>
         <RECIPIENT>Foo</RECIPIENT>
         <PAYLOAD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns="http://www.payload.org"
                  xsi:schemaLocation="http://www.payload.org xsd/payload-type-a.xsd">
              <!-- Large message containing many possible elements -->
         </PAYLOAD>
    <MESSAGE>
</MESSAGES>

我也可以做相反的事情,即验证 MESSAGES 包装器,但忽略 PAYLOAD,在整个 XML 上使用以下 XSD:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.message.org">
     <xs:element name="MESSAGES">
         <xs:complexType>
             <xs:sequence>
                 <xs:element name="MESSAGE" maxOccurs="unbounded">
                     <xs:complexType>
                         <xs:sequence>
                             <xs:element name="RECIPIENT" type="xs:string"/>
                             <xs:any processContents="skip"/>
                         </xs:sequence>
                    </xs:complexType>
                 </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

使用 XML:

<MESSAGES xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://www.messages.org"
          xsi:schemaLocation="http://www.messages.org xsd/messages.xsd">
    <MESSAGE>
         <RECIPIENT>Foo</RECIPIENT>
         <PAYLOAD>
              <!-- Large message containing many possible elements -->
         </PAYLOAD>
    <MESSAGE>
</MESSAGES>

但我不能做的是在 XML 中结合 两个 XSD:

<MESSAGES xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://www.messages.org"
          xsi:schemaLocation="http://www.messages.org xsd/messages.xsd">
    <MESSAGE>
         <RECIPIENT>Foo</RECIPIENT>
         <PAYLOAD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns="http://www.payload.org"
                  xsi:schemaLocation="http://www.payload.org xsd/payload-type-a.xsd">
              <!-- Large message containing many possible elements -->
         </PAYLOAD>
    <MESSAGE>
</MESSAGES>

我对 XSD 很陌生,所以我可以看出我正在尝试做的事情可能不是 XML/Validation 的精神,但它确实让我觉得想做一件合理的事情 - 我'如果我是第一个提出反对意见的人,我会感到惊讶!

我能想到的唯一理论上的解决方案是让 XSD 本身由生成 MESSAGES 的 XSLT 动态生成。也就是说,让 XSLT(为简洁起见省略),同时输出 XML 和 Schema 来验证它。然后我可以使用 XSD 导入语句,因为 XSLT 文档到 PAYLOAD 类型的映射是一对一的。

然而,这会使事情变得非常复杂!

我希望有一种方法可以验证具有不同架构的 XML 文件的不同部分,并从 XML 文件本身进行控制。

任何想法都非常感谢!

【问题讨论】:

    标签: xml xsd xsd-validation xml-validation


    【解决方案1】:

    我最终得到了这个工作。现实情况是,我认为我做错了一些小事,这意味着我在兜圈子。最终,我能够生成以下内容 - 唯一缺少的是 xs:schema 属性中的 elementFormDefault="qualified",如果模式验证正确,processContents 应该是 strict

    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
               targetNamespace="http://www.message.org"
               elementFormDefault="qualified">
         <xs:element name="MESSAGES">
             <xs:complexType>
                 <xs:sequence>
                     <xs:element name="MESSAGE" maxOccurs="unbounded">
                         <xs:complexType>
                             <xs:sequence>
                                 <xs:element name="RECIPIENT" type="xs:string"/>
                                 <xs:any processContents="strict"/>
                             </xs:sequence>
                        </xs:complexType>
                     </xs:element>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    </xs:schema>
    

    有了这个 XSD,我能够让以下 XML 工作:

    <MESSAGES xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://www.messages.org"
              xsi:schemaLocation="http://www.messages.org xsd/messages.xsd">
        <MESSAGE>
             <RECIPIENT>Foo</RECIPIENT>
             <PAYLOAD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xmlns="http://www.payload.org"
                      xsi:schemaLocation="http://www.payload.org xsd/payload-type-a.xsd">
                  <!-- Large message containing many possible elements -->
             </PAYLOAD>
        <MESSAGE>
    </MESSAGES>
    

    最后值得注意的是,您可以在 XML 的顶部添加多个模式,然后通过更改 xmlns 来选择它们,就像上面的示例一样:

    <MESSAGES xsi:schemaLocation="http://www.messages.org xsd/messages.xsd
                                  http://www.payload.org xsd/payload.xsd>"
    

    【讨论】:

      猜你喜欢
      • 2011-01-02
      • 1970-01-01
      • 2010-09-06
      • 1970-01-01
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      • 1970-01-01
      • 2014-05-20
      相关资源
      最近更新 更多