2

My aim is to make a modular XML schema that has some shared types in one file available to all subschema files. What's the best way to go around this?

Example:

Say I want to build an XML schema which describes XML documents about cars and bikes. I then create a schema for the XML, which I divide up into 4 files: vehicles.xsd, cars.xsd, bikes.xsd and types.xsd. vehicles.xsd includes cars.xsd and bikes.xsd and they both in turn include types.xsd. I noticed when trying out this example with the command

xmllint --schema vehicles.xsd vehicles.xml

that it validates fine, even though I was expecting a conflict to arise because of the double inclusion of types.xsd (which leads to 2 definitions of the complexType vehicleType). Removing the <include> tag from either cars.xsd or bikes.xsd also validates just fine. Can someone explain to me what is going on here?

XML and XSDs:

vehicles.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>

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>

cars.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>

bikes.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>

types.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>
4

2 回答 2

2

大多数 XSD 处理器会注意到,当被要求包含类似 types.xsd 的模式文档时,它们已经包含了它,并且避免再次包含它;XSD 规范明确鼓励这样做。这就是为什么您没有收到关于双重包含的错误消息的原因,以及为什么单一包含对于合并的情况可以正常工作。

但是,总的来说,如果您通过从单个顶级驱动程序文件中执行所有包含来使事情变得更简单,那么 XSD 处理器之间的互操作性会稍好一些。如果您使用该惯用语,您将从所有架构文档中删除 xs:include 元素,并制作一个或多个新的驱动程序文档,其中只包含包含项(如果您只需要一个架构,则为一个;如果您想要不同的,则需要多个驱动程序文档具有不同元素集的模式)。

类似的考虑适用于在 xs:import 元素上使用 schemaLocation 属性。使用这个习惯用法有助于避免从不同处理器产生显着不同结果的情况(尤其是涉及重新定义和引用周期的情况)。

于 2013-06-19T16:01:00.293 回答
0

从 XML 模式的 W3C 规范来看,我相信它的目的是能够拥有模块化模式,并且可以在需要的地方包含它们。xml 处理器的预处理器应该首先解析所有包含和“导入”。

我确实有一个广泛的模式,它被分解成小的模块化部分。这适用于许多 xlm 处理器和 xml 编辑器。

于 2014-12-07T14:29:23.940 回答