动态 XML 架构验证文档的子部分
Dynamic XML Schema Validates Subsection of Document
我的情况类似于“XSD with elements from other namespace”,我有 2 个 XML。
XML 的一个作为另一个的包装器。在一个简单的示例中 - 我们有一个 MESSAGES 包装器,至少包含一个 MESSAGE 元素。每个 MESSAGE 元素都包含一个 PAYLOAD,它根据 XSD.
进行验证
给定 MESSAGES 父级中的每个 PAYLOAD 都将针对相同的 XSD 进行验证。但是,不同的 MESSAGES 可以包含针对整个 XSD 主机进行验证的 PAYLOAD。我确实有数百个 XSD 来验证不同类型的 PAYLOAD。
我想拥有自己的 XSD 来验证 MESSAGES 包装器的结构,然后将验证 PAYLOAD 的责任移交给我拥有的众多 XSD 之一,具体取决于有效负载类型。
重要的一点是我们不能将 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:
中合并 both XSDs
<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 本身由生成消息的 XSLT 动态生成。也就是说,拥有 XSLT(为简洁起见省略),同时输出 XML 和 Schema 以验证它。然后我可以使用 XSD import 语句,因为存在 XSLT 文档到 PAYLOAD 类型的一对一映射。
然而,这会使事情变得非常复杂!
我希望有一种方法可以使用不同的模式验证 XML 文件的不同部分,并从 XML 文件本身控制它。
非常感谢任何想法!
我最终成功了。事实上,我认为我做错了一些小事,这意味着我在兜圈子。最终我能够生成以下内容 - 唯一缺少的是 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
来 select 它们,就像上面的示例一样:
<MESSAGES xsi:schemaLocation="http://www.messages.org xsd/messages.xsd
http://www.payload.org xsd/payload.xsd>"
我的情况类似于“XSD with elements from other namespace”,我有 2 个 XML。
XML 的一个作为另一个的包装器。在一个简单的示例中 - 我们有一个 MESSAGES 包装器,至少包含一个 MESSAGE 元素。每个 MESSAGE 元素都包含一个 PAYLOAD,它根据 XSD.
进行验证给定 MESSAGES 父级中的每个 PAYLOAD 都将针对相同的 XSD 进行验证。但是,不同的 MESSAGES 可以包含针对整个 XSD 主机进行验证的 PAYLOAD。我确实有数百个 XSD 来验证不同类型的 PAYLOAD。
我想拥有自己的 XSD 来验证 MESSAGES 包装器的结构,然后将验证 PAYLOAD 的责任移交给我拥有的众多 XSD 之一,具体取决于有效负载类型。
重要的一点是我们不能将 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:
中合并 both XSDs<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 本身由生成消息的 XSLT 动态生成。也就是说,拥有 XSLT(为简洁起见省略),同时输出 XML 和 Schema 以验证它。然后我可以使用 XSD import 语句,因为存在 XSLT 文档到 PAYLOAD 类型的一对一映射。
然而,这会使事情变得非常复杂!
我希望有一种方法可以使用不同的模式验证 XML 文件的不同部分,并从 XML 文件本身控制它。
非常感谢任何想法!
我最终成功了。事实上,我认为我做错了一些小事,这意味着我在兜圈子。最终我能够生成以下内容 - 唯一缺少的是 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
来 select 它们,就像上面的示例一样:
<MESSAGES xsi:schemaLocation="http://www.messages.org xsd/messages.xsd
http://www.payload.org xsd/payload.xsd>"