我的目标是创建一个模块化的 XML 模式,该模式在一个文件中具有一些共享类型,可供所有子模式文件使用。解决这个问题的最佳方法是什么?
示例:
假设我想构建一个 XML 模式来描述有关汽车和自行车的 XML 文档。然后,我为 XML 创建一个架构,并将其分为 4 个文件: vehicles.xsd
, cars.xsd
, bikes.xsd
和types.xsd
。 vehicles.xsd
包括cars.xsd
和bikes.xsd
它们又都包括 types.xsd
。我在使用命令尝试这个示例时注意到
xmllint --schema vehicles.xsd vehicles.xml
它验证得很好,尽管我预计由于 types.xsd
的双重包含而会出现冲突。 (这导致了复杂类型 vehicleType
的 2 个定义)。删除<include>
来自 cars.xsd
的标签或bikes.xsd
也验证得很好。有人可以向我解释一下这是怎么回事吗?
XML 和 XSD:
车辆.xml:
<vehicles xmlns="http://example.com/vehicles">
<cars>
<car make="Porsche" model="911" />
<car make="Porsche" model="911" />
</cars>
<bikes>
<bike make="Harley-Davidson" model="WL" />
<bike make="Yamaha" model="XS650" />
</bikes>
</vehicles>
车辆.xsd:
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vh="http://example.com/vehicles"
targetNamespace="http://example.com/vehicles"
elementFormDefault="qualified">
<xs:include schemaLocation="cars.xsd" />
<xs:include schemaLocation="bikes.xsd" />
<xs:element name="vehicles">
<xs:complexType>
<xs:sequence>
<xs:element ref="vh:cars" />
<xs:element ref="vh:bikes" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
汽车.xsd:
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vh="http://example.com/vehicles"
targetNamespace="http://example.com/vehicles"
elementFormDefault="qualified">
<xs:include schemaLocation="types.xsd" />
<xs:element name="cars">
<xs:complexType>
<xs:sequence>
<xs:element name="car" type="vh:vehicleType"
minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
自行车.xsd:
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vh="http://example.com/vehicles"
targetNamespace="http://example.com/vehicles"
elementFormDefault="qualified">
<xs:include schemaLocation="types.xsd" />
<xs:element name="bikes">
<xs:complexType>
<xs:sequence>
<xs:element name="bike" type="vh:vehicleType"
minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
类型.xsd
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/vehicles">
<xs:complexType name="vehicleType">
<xs:attribute name="make" type="xs:string" />
<xs:attribute name="model" type="xs:string" />
</xs:complexType>
</xs:schema>
最佳答案
大多数 XSD 处理器都会注意到,当被要求包含像 types.xsd 这样的模式文档时,当他们已经包含它时,他们会避免再次包含它; XSD 规范明确鼓励这样做。这就是为什么您不会收到关于双重包含的错误消息,以及为什么单一包含对于合并的情况效果很好的原因。
但是,一般来说,如果您通过从单个顶级驱动程序文件中执行所有包含操作来使事情变得更简单,那么 XSD 处理器之间的互操作性会稍微好一些。如果您使用该习惯用法,则可以从所有架构文档中删除 xs:include 元素,并创建一个或多个新的驱动程序文档,其中只包含包含项(如果您只需要一个架构,则创建一个;如果您想要不同的驱动程序文档,则创建多个驱动程序文档)具有不同元素集的模式)。
类似的注意事项适用于 xs:import 元素上 schemaLocation 属性的使用。使用此习惯用法有助于避免不同处理器产生截然不同的结果的情况(尤其是涉及重新定义和引用循环的情况)。
关于include - 部分模式包含在多个子模式中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17156899/