XSD:应允许以不同形式使用一个元素

时间:2012-03-15 11:11:22

标签: xml xsd stylesheet

使用XSD,我想定义一个复杂的元素,它可以以三种不同的形式出现:

<Scope Name="foo" />  <!-- no children -->
<Scope Name="foo" Src="bar" /> <!-- When Src is present, there must be no children! -->
<Scope Name="foo"><!-- other children --></Scope>

在第三种情况下,它可以很好地定义为儿童元素(例如,所有三种类型的“范围”)。重要的是,具有“Src”属性的Scope元素必须为空!

此外,在不同的地方,我只想要特定类型的元素。例如,在根标记内,我想要允许第三种类型的一个Scope元素;在大多数情况下,我会允许所有情况。这就是问题:如何解决这个问题?

到目前为止我做了什么:我为3个案例中的每一个创建了一个复杂类型,我可以在其中使用。但是,我不能使用:

<xs:choice minOccurs="0" maxOccurs="unbounded">
    <xs:element name="Scope" type="type_Scope_WithSrc" />
    <xs:element name="Scope" type="type_Scope_WithContent" />
    <xs:element name="Scope" type="type_Scope_Base" />
</xs:choice>

我尝试创建这些联合,但只允许使用简单类型的联合。

我还试图定义一个整体类型“type_Scope”,它使用xs:choice来包含它们。但是xs:choice会包含xs:elements,在这种情况下也需要一个名字: - (

你能告诉我如何处理这件事吗?

请不要告诉我XSD是不可能的:-(: - (

谢谢

此致 DIVB

1 个答案:

答案 0 :(得分:2)

您可能会得到不同的答案,具体取决于您是否希望使用XSD 1.1或XSD 1.0实现此目的;我会假设您正在使用1.0解决方案,我将在此处描述(我不相信1.1是实用的)。

如果要保留元素名称并更改其内容,此处唯一的选择是使用xsi:type。而不是选择,只需使用一个Scope元素;使其类型为复杂类型,其属性名为“Name”。是否有其他两种类型从此基本类型扩展。你已经完成了。

注意:我使用基本抽象类型作为一种机制来告知人们其他类型应该进入那里;现实是,即使没有它,它也会起作用,从一开始就使用type_Scope_Base。

Type hierarchy

XSD:

<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/XMLSchema.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:complexType name="type_Scope_BaseA" abstract="true">
    </xsd:complexType>  

    <xsd:complexType name="type_Scope_Base">
        <xsd:complexContent>
            <xsd:extension base="type_Scope_BaseA">
                <xsd:attribute name="Name" type="xsd:string"/>      
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>  

    <xsd:complexType name="type_Scope_WithSrc">
        <xsd:complexContent>
            <xsd:extension base="type_Scope_Base">
                <xsd:attribute name="Src" type="xsd:string"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="type_Scope_WithContent">
        <xsd:complexContent>
            <xsd:extension base="type_Scope_Base">
                <xsd:sequence>
                    <xsd:any maxOccurs="unbounded" namespace="##other" processContents="lax"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:element name="root">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="Scope"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:element name="Scope" type="type_Scope_BaseA"/>

</xsd:schema>

这三个示例XML都是有效的。第一个内容模型来自type_Scope_Base

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
    <Scope xsi:type="type_Scope_Base" Name="Name1"/>
</root>

这是来自type_Scope_WithSrc的内容模型。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
    <Scope xsi:type="type_Scope_WithSrc" Name="Name1" Src="Src1"/>
</root>

这是来自type_Scope_WithContent的内容模型。

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
    <Scope xsi:type="type_Scope_WithContent" Name="Name1">
        <me:hello.you xmlns:me="http://paschidev.com"/>
    </Scope>
</root>

如果你想允许标签名称的变化,而不是选择你可以放置替换组的头部,这至少可以给你一个没有xsi:type的解决方案。

然后有基于XSD 1.1的解决方案,但我会在开放的环境中远离类似的东西;今天不是每个人都有一个兼容的处理器,更不用说规范本身不是一个推荐。