我不确定我的问题的标题是否正确,我不认为这被称为“嵌入式”文档,但我不知道确切的术语。所以,首先:“这个人意味着什么?”
<somedocument>
<item cost="34">
<name>Apple</name>
<description>A delicious apple!</description>
<details xmlns:apple="http://example.org/apples">
<apple:color>red</apple:color>
<apple:cultivar>Braeburn</apple:cultivar>
</details>
</item>
</somedocument>
现在我想使用XMLSchema验证此文档。我会为文档的所有通用细节创建一个模式,比如项目结构等。我知道我可以使用<xsd:any>
允许其他文档中的任何其他XML,我可以使用它来允许<details>
部分中的苹果特定元素。到目前为止,非常好。
但是如果我想验证http://example.org/apples
命名空间中的所有元素呢?鉴于该文件不仅限于苹果,可能还有香蕉,猕猴桃和桃子,未来可能会有更多的“嵌入式”文件。
我错过了XMLSchema中的哪些内容可以帮助我做到这一点?如果没有,在这种情况下你会怎么做?您能想到的替代品有哪些?由于我还使用Schemas进行文档管理,“只需解析文档并自行验证代码中的所有<details>
”解决方案并不理想。
提前谢谢!
修改的: 在再次阅读完整个问题之后,有一个重点缺失:
<details>
部分不限于示例中所示的键/值对,因此使用通用键/值解法替换整个命名空间和自定义元素内容不起作用。答案 0 :(得分:2)
您无法轻松实现指定的确切架构设计(details元素可以包含可变内容)。考虑XML验证器的工作原理:它需要预览<details>
元素的内容以确定内容的类型。有一个相关的讨论here。
但是,您可以通过两种方式之一实现类似的效果。在您控制整个架构的情况下,我建议选项2,因为它更简单(当扩展类型可能在外部文档中时,选项1更好,例如第三方架构)。
在XSD中使用继承和多态时,在XSD中定义一个抽象的ComplexType,然后定义一个或多个扩展它的类型。您将抽象类型指定为item
元素的成员,但在XML文档中,您可以使用xsi:type
属性指定具体类型。使用此技术,您的XML文档将如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<somedocument
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://grocery.example.com/schema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item cost="34">
<name>Apple</name>
<description>A delicious apple!</description>
<details xsi:type="AppleDetails">
<color>red</color>
<cultivar>Braeburn</cultivar>
</details>
</item>
<item cost="32">
<name>Baked Beans</name>
<description>A tin of beans.</description>
<details xsi:type="BeansDetails">
<manufacturer>Heinz</manufacturer>
<size>440g</size>
</details>
</item>
</somedocument>
以下是上述示例的架构:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://grocery.example.com/schema"
xmlns="http://grocery.example.com/schema">
<xs:complexType name="ItemDetails" abstract="true" />
<xs:complexType name="AppleDetails">
<xs:complexContent>
<xs:extension base="ItemDetails">
<xs:sequence>
<xs:element minOccurs="0" name="color" type="xs:string" />
<xs:element minOccurs="0" name="cultivar" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="BeansDetails">
<xs:complexContent>
<xs:extension base="ItemDetails">
<xs:sequence>
<xs:element minOccurs="0" name="manufacturer" type="xs:string" />
<xs:element minOccurs="0" name="size" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="somedocument">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="item">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element name="description" type="xs:string" />
<xs:element name="details" type="ItemDetails" />
</xs:sequence>
<xs:attribute name="cost" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
<xs:choice>
使用<xs:choice>
元素时,可以指定可在<item>
元素中使用的多个互斥元素。这是文档的样子:
<?xml version="1.0" encoding="utf-8" ?>
<somedocument
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://grocery.example.com/schema/2">
<item cost="34">
<name>Apple</name>
<description>A delicious apple!</description>
<appleDetails>
<color>red</color>
<cultivar>Braeburn</cultivar>
</appleDetails>
</item>
<item cost="32">
<name>Baked Beans</name>
<description>A tin of beans.</description>
<beansDetails>
<manufacturer>Heinz</manufacturer>
<size>440g</size>
</beansDetails>
</item>
</somedocument>
相应的模式比选项1简单得多,但要求在<xs:choice>
中使用之前预先定义所有项目详细信息类型。架构如下所示:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://grocery.example.com/schema/2"
xmlns="http://grocery.example.com/schema/2">
<xs:complexType name="AppleDetails">
<xs:sequence>
<xs:element minOccurs="0" name="color" type="xs:string" />
<xs:element minOccurs="0" name="cultivar" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="BeansDetails">
<xs:sequence>
<xs:element minOccurs="0" name="manufacturer" type="xs:string" />
<xs:element minOccurs="0" name="size" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="somedocument">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="item">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
<xs:element name="description" type="xs:string" />
<xs:choice>
<xs:element name="appleDetails" type="AppleDetails" />
<xs:element name="beansDetails" type="BeansDetails" />
</xs:choice>
</xs:sequence>
<xs:attribute name="cost" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
因为您控制整个架构,并且可以将所有内容保存在单个XSD架构文档中,所以更好的选择可能是选项2.
另外,请考虑如何对架构进行版本化(请参阅here以获取一些建议),以便您可以扩展架构并添加新项类型,而不会破坏向后兼容性。
答案 1 :(得分:1)
我希望我能正确理解这个问题......在<details>
内,你想要允许来自任何命名空间的任何元素,但是如果这些元素在http://example.org/apples
中(SIR我必须问你,请做你拥有EXAMPLE.ORG DOMAIN?:D),那么你想要验证那些。
很容易。
在主模式文件someschema.xsd
中,执行以下操作:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:someschema"
elementFormDefault="qualified"
>
<xs:import namespace="http://example.org/apples" schemaLocation="apples.xsd" />
<!-- rest of your schema here -->
<xs:complexType name="details">
<xs:sequence maxOccurs="unbounded">
<xs:any minOccurs="0" processContents="lax" />
</xs:sequence>
</xs:complexType>
</xs:schema>
创建apples.xsd
:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.org/apples"
elementFormDefault="qualified"
>
<xs:element name="color">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="red" />
<xs:enumeration value="green" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="cultivar">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="Braeburn" />
<xs:enumeration value="Granny Smith" />
<xs:enumeration value="McIntosh" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:schema>
???
重要的是,对于那些你想要在<details>
内验证的外部名称空间,你需要在模式的顶部导入相应的模式文件。
这实际上利用了这样一个事实,即XML Schema完全被延迟,甚至无法定义文档的根元素。从理论上讲,您也可以省略<import>
,而只是针对someschema.xsd
和apples.xsd
验证您的文档(尽管尚未对此进行测试)。