是否可以将根元素限制为从指定父类型派生的类型?

时间:2015-10-21 08:44:43

标签: xml xsd

让我们从一个简单的架构开始:

<xs:complexType name="AnimalType" abstract="true">
    <xs:sequence>
        <xs:element name="legs" xml:base="xs:nonNegativeInteger"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="DogType">
    <xs:complexContent>
        <xs:extension base="AnimalType">
            <xs:sequence>
                <xs:element name="furColor" xml:base="xs:string"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

<xs:complexType name="BirdType">
    <xs:complexContent>
        <xs:extension base="AnimalType">
            <xs:sequence>
                <xs:element name="canFly" xml:base="xs:boolean"/>
            </xs:sequence>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>

是否可以定义可以是任何动物类型的名为xs:element的根pet?即使这两个文件有效:

<!-- a dog -->
<pet>
    <legs>4</legs>
    <furColor>black</furColor>
</pet>


<!-- a bird -->
<pet>
    <legs>2</legs>
    <canFly>true</canFly>
</pet>

添加<xs:element name="pet" type="AnimalType"/>不起作用,因为AnimalType是抽象的(即使它不是我仍然无法从派生类型添加子元素)。

我需要pet作为AnimalType的实例,因此将pet的类型设置为xs:anyType不是一种选择。

2 个答案:

答案 0 :(得分:2)

不,并且需要注释来区分这两个pet案例的事实应该被视为这里应该质疑XML设计目标的信号,而不是XSD的能力。

以下是几种替代XML设计:

  1. 文档可以有不同的根节点可能性,所以很简单 允许dogbird根元素及其各自的元素 类型都来自公共AnimalType
  2. XSD 1.1支持Conditional Type Assignment (CTA),因此请添加属性 AnimalType可以通过测试来区分DogType和。{1}} BirdType根元素的pet替代可能性。您可以找到example of CTA here
  3. 我赞成#1。

答案 1 :(得分:1)

一种可能性是通过xsi:type明确指定元素的类型。

对于狗,您可以使用(假设您的模式已保存在animals.xsd中):

<?xml version="1.0" encoding="UTF-8"?>
<pet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="animals.xsd" xsi:type="DogType">
    <legs>4</legs>
    <furColor>red</furColor>
</pet>

对于鸟:

<?xml version="1.0" encoding="UTF-8"?>
<pet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="animals.xsd" xsi:type="BirdType">
    <legs>2</legs>
    <canFly>true</canFly>
</pet>