如何在不对选择进行排序的情况下扩展选择complexType?

cev*_*ing 19 xsd

我有一个选择complexType命名abType:

<xs:complexType name="abType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="a"/>
        <xs:element name="b"/>
    </xs:choice>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

此类型可用于以任何顺序创建具有ab节点的元素,例如:

<ab>
    <b/>
    <a/>
</ab>
Run Code Online (Sandbox Code Playgroud)

现在我想创建一个派生类型,调用abcType以允许节点a,bc以任何顺序.因此我基于以下方式创建了一个新的complexType abType:

<xs:complexType name="abcType">
    <xs:complexContent>
        <xs:extension base="abType">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="c"/>
            </xs:choice>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

之后我创建了一个abc节点:

<abc>
    <c/>
    <b/>
    <a/>
</abc>
Run Code Online (Sandbox Code Playgroud)

但是这个节点无效!放置任何ab之后无效c.原因是,从基类型派生类型会创建一个隐含序列,尽管两种类型都是选择.XMLspy以这种方式说明了它:

扩展选择类型

这个结果对于选择类型来说是无用的.

所以我的问题是:如何在不对选择进行排序的情况下扩展选择类型?

以下是完整的XSD和用于重现问题的XML测试文件:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="root">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="ab"/>
            <xs:element ref="abc"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>
<xs:element name="ab" type="abType"/>
<xs:complexType name="abType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="a"/>
        <xs:element name="b"/>
    </xs:choice>
</xs:complexType>
<xs:element name="abc" type="abcType"/>
<xs:complexType name="abcType">
    <xs:complexContent>
        <xs:extension base="abType">
            <xs:choice minOccurs="0" maxOccurs="unbounded">
                <xs:element name="c"/>
            </xs:choice>
        </xs:extension>
    </xs:complexContent>
</xs:complexType>
</xs:schema>
Run Code Online (Sandbox Code Playgroud)

例:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="inherit-choice.xsd">
<ab>
    <b/>
    <a/>
</ab>
<abc>
    <c/>
    <b/>
    <a/>
</abc>
</root>
Run Code Online (Sandbox Code Playgroud)

小智 15

有一种方法可以做到这一点,这取决于选择中的选择是一个更大的选择.

首先,定义一个元素组,该元素组包含基本元素中所有元素的单个选项:

<xs:group name="common_ab_elements">
    <xs:choice>
        <xs:element name="a"/>
        <xs:element name="b"/>
    </xs:choice>
</xs:group>
Run Code Online (Sandbox Code Playgroud)

然后你可以在你的abElement定义中使用它来代替你之前的元素:

<xs:complexType name="abType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:group ref="common_ab_elements"/>
    </xs:choice>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

如果您需要扩展类型,那么您可以扩展选择:

<xs:complexType name="abcType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:group ref="common_ab_elements"/>
        <xs:element name="c"/>
    </xs:choice>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

这相当于:

<xs:complexType name="abcType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:choice>
            <xs:element name="a"/>
            <xs:element name="b"/>
        </xs:choice>
        <xs:element name="c"/>
    </xs:choice>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

而且由于选择操作的性质,这又相当于:

<xs:complexType name="abcType">
    <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="a"/>
        <xs:element name="b"/>
        <xs:element name="c"/>
    </xs:choice>
</xs:complexType>
Run Code Online (Sandbox Code Playgroud)

......这就是你想要的.

如果您也有属性,那么您可能还需要定义一个可以扩展的公共基类.使用此方案,只有没有派生类的类才应该有元素,因为基本元素上存在强制排序的元素.

我们在这里有效地做的是将选择元素的继承与元素层次结构本身分开定义.


Pet*_*dea 11

不幸的是,简短的回答是NO,你无法扩展选择合成器.从逻辑上讲,如果a,b和c之间存在某种关系(如在Java,.NET中,一切最终都是对象,您可以在XSD中执行相同的操作),那么我建议使用替换组(或者,如果你愿意,可以选择基于xsi:type的东西.

更新一个例子.XSD-1:

<?xml version="1.0" encoding="utf-8" ?>
<!--W3C Schema generated by QTAssistant/W3C Schema Refactoring Module (http://www.paschidev.com)-->
<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:element name="ab" type="abType"/>

    <xsd:complexType name="abType">
        <xsd:sequence>
            <xsd:element ref="ExtensibleChoice-A" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:element name="ExtensibleChoice-A" type="ExtensibleChoiceBaseType" abstract="true" />

    <xsd:complexType name="ExtensibleChoiceBaseType" abstract="true">
        <xsd:sequence/>
    </xsd:complexType>

    <xsd:element name="a" substitutionGroup="ExtensibleChoice-A" type="aType" block="#all"/>
    <xsd:element name="b" substitutionGroup="ExtensibleChoice-A" type="bType" block="#all"/>
    <xsd:element name="c" substitutionGroup="ExtensibleChoice-A" type="cType" block="#all"/>

    <xsd:complexType name="aType">
        <xsd:complexContent>
            <xsd:extension base="ExtensibleChoiceBaseType">
                <xsd:sequence>
                    <xsd:element name="aChild" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="bType">
        <xsd:complexContent>
            <xsd:extension base="ExtensibleChoiceBaseType">
                <xsd:sequence>
                    <xsd:element name="bChild" type="xsd:int"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    <xsd:complexType name="cType">
        <xsd:complexContent>
            <xsd:extension base="ExtensibleChoiceBaseType">
                <xsd:sequence>
                    <xsd:element name="cChild" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>
Run Code Online (Sandbox Code Playgroud)

替换组的成员

可扩展性是指在某个时间点,您可能只有a,bc作为成员.如果您或消费者决定添加某些内容(例如d元素),那么您只需使用新元素d创建另一个引用旧模式的模式,然后使用该新模式.旧的XSD文件没有被触及; 生成新的JAXB类(作为示例)将导致向后兼容的代码.

所以,XSD-1将验证这样的事情:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<ab xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd">
    <a>
        <aChild>aChild1</aChild>
    </a>
    <b>
        <bChild>1</bChild>
    </b>
    <c>
        <cChild>cChild1</cChild>
    </c>
</ab>
Run Code Online (Sandbox Code Playgroud)

XSD-1的XML示例

你需要这样的东西(XSD-2):

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

    <xsd:import namespace="http://tempuri.org/XMLSchema.xsd" schemaLocation="XSD-1.xsd"/>

    <xsd:element name="d" substitutionGroup="b:ExtensibleChoice-A" type="dType" block="#all"/>

    <xsd:complexType name="dType">
        <xsd:complexContent>
            <xsd:extension base="b:ExtensibleChoiceBaseType">
                <xsd:sequence>
                    <xsd:element name="dChild" type="xsd:string"/>
                </xsd:sequence>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>
Run Code Online (Sandbox Code Playgroud)
  • 该图显示了"新"成员列表,d以蓝色突出显示:

扩展替换组成员列表

要验证这一点:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<ab xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://tempuri.org/XMLSchema.xsd" xmlns:d="http://tempuri.org/XMLSchema1.xsd">
    <a>
        <aChild>aChild1</aChild>
    </a>
    <d:d>
        <d:dChild>1</d:dChild>
    </d:d>
</ab>
Run Code Online (Sandbox Code Playgroud)

示例XML显示新成员