我有以下xsd架构:
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Vehicle">
<xs:sequence>
<xs:element name="numberOfWheels" type="xs:int" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="car" type="Car"/>
<xs:complexType name="Car">
<xs:complexContent>
<xs:extension base="Vehicle">
<xs:sequence>
<xs:element name="numberOfSeats" type="xs:int" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="motorCycle" type="MotorCycle"/>
<xs:complexType name="MotorCycle">
<xs:complexContent>
<xs:extension base="Vehicle">
<xs:sequence>
<xs:element name="hasLuggageCompartment" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="wagon" type="Wagon"/>
<xs:complexType name="Wagon">
<xs:complexContent>
<xs:extension base="Vehicle">
<xs:sequence>
<xs:element name="typeOfCargo" type="xs:string" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="vehicleList" type="VehicleList"/>
<xs:complexType name="VehicleList">
<xs:sequence>
<xs:element <!-- what to do here? --> minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
如图所示,我们有类型&#34; Car&#34;,&#34; MotorCycle&#34;和&#34; Wagon&#34;,所有这些都扩展了&#34; Vehicle&#34;类型。
我现在想在我的模式(VehicleList)中引入一个容器元素,它允许存储任何类型的元素,只要它扩展&#34; Vehicle&#34;,以便我们可以存储类型&#34的元素; Car&#34;,&#34; MororCycle&#34;或者&#34; Wagon&#34;,但不是,例如,&#34; Cow&#34;因为他们会扩展动物&#34;类型。
我已经搜索了很多,我认为不可能在XML模式中引入这种限制,基于&#34;祖先&#34;类型,就像我们在OO编程中经常习惯的那样。
所以我的问题:是否可以声明一个容器元素,根据它们扩展的类型限制它包含的元素,如果是的话,怎么做?
提前感谢您的回答和建议。
答案 0 :(得分:1)
使用ComplexTypes和xsi:type
最简单,最易扩展的方法是将类型设置为Vehicle。
<xs:complexType name="VehicleList">
<xs:sequence>
<xs:element name="VehicleElm"
type="Vehicle"
minOccurs="1"
maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
然而,生成的XML看起来像这样,可能不完全是你想要的(添加了xsi:type属性)
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Studio 2018 - Developer Bundle 16.0.0.0 (https://www.liquid-technologies.com) -->
<vehicleList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="XSDFile.xsd">
<VehicleElm xsi:type="Car">
<numberOfWheels>4</numberOfWheels>
<numberOfSeats>2</numberOfSeats>
</VehicleElm>
<VehicleElm xsi:type="Wagon">
<numberOfWheels>6</numberOfWheels>
<typeOfCargo>stuff</typeOfCargo>
</VehicleElm>
</vehicleList>
使用替换组
另一种方法是使用替换组,它在XSD中稍微复杂一些,但提供更清晰的XML
<?xml version="1.0" encoding="utf-8" ?>
<!--Created with Liquid Studio 2018 - Developer Bundle 16.0.0.0 (https://www.liquid-technologies.com)-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="VehicleType">
<xs:sequence>
<xs:element name="numberOfWheels"
type="xs:int"
minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:complexType>
<xs:element name="Vehicle"
type="VehicleType"
abstract="true" />
<xs:element name="car"
substitutionGroup="Vehicle">
<xs:complexType>
<xs:complexContent>
<xs:extension base="VehicleType">
<xs:sequence>
<xs:element name="numberOfSeats"
type="xs:int"
minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="motorCycle"
substitutionGroup="Vehicle">
<xs:complexType>
<xs:complexContent>
<xs:extension base="VehicleType">
<xs:sequence>
<xs:element name="hasLuggageCompartment"
type="xs:boolean"
minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="wagon"
substitutionGroup="Vehicle">
<xs:complexType>
<xs:complexContent>
<xs:extension base="VehicleType">
<xs:sequence>
<xs:element name="typeOfCargo"
type="xs:string"
minOccurs="0"
maxOccurs="1" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="vehicleList"
type="VehicleList" />
<xs:complexType name="VehicleList">
<xs:sequence>
<xs:element ref="Vehicle"
minOccurs="1"
maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:schema>
生成的XML看起来像这样
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Liquid Studio 2018 - Developer Bundle 16.0.0.0 (https://www.liquid-technologies.com) -->
<vehicleList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="XSDFile2.xsd">
<car>
<numberOfWheels>4</numberOfWheels>
<numberOfSeats>2</numberOfSeats>
</car>
<motorCycle>
<numberOfWheels>2</numberOfWheels>
<hasLuggageCompartment>false</hasLuggageCompartment>
</motorCycle>
</vehicleList>
基本上你可以使用元素Vehicle,任何替换组成员都可以在它的位置使用,并且因为Vehicle元素是抽象的,所以它不能自己使用(所以你必须使用它取代组成员)。