我可以选择名为abType
的复杂类型:
<xs:complexType name="abType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="a"/>
<xs:element name="b"/>
</xs:choice>
</xs:complexType>
此类型可用于以任何顺序创建具有a
和b
节点的元素,例如:
<ab>
<b/>
<a/>
</ab>
现在我想创建一个名为abcType
的派生类型,以便以任何顺序允许节点a
,b
和c
。因此,我基于abType
创建了一个新的complexType:
<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>
之后我创建了一个abc
节点:
<abc>
<c/>
<b/>
<a/>
</abc>
但此节点无效!在a
之后放置任何b
或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>
示例:
<?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>
答案 0 :(得分:14)
有一种方法可以做到这一点,这取决于选择中的选择是一个更大的选择。
首先,定义一个元素组,其中包含基本元素中所有元素的单一选择:
<xs:group name="common_ab_elements">
<xs:choice>
<xs:element name="a"/>
<xs:element name="b"/>
</xs:choice>
</xs:group>
然后你可以在你的abElement定义中使用它代替你之前的元素:
<xs:complexType name="abType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="common_ab_elements"/>
</xs:choice>
</xs:complexType>
如果您需要扩展类型,那么您可以扩展选择:
<xs:complexType name="abcType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:group ref="common_ab_elements"/>
<xs:element name="c"/>
</xs:choice>
</xs:complexType>
这相当于:
<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>
由于选择操作的性质,这又相当于:
<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>
......这就是你想要的。
如果您也有属性,那么您可能还需要定义一个可以扩展的公共基类。使用这种方案,只有没有派生类的类才应该有元素,因为基本元素上存在强制排序的元素。
我们在这里有效地做的是与元素层次结构本身分开定义选择元素的继承。
答案 1 :(得分:11)
更新一个例子。 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>
可扩展性是指在某个时间点,您可能只有 a , b 和 c 作为成员。如果您或消费者决定添加某些内容(例如 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>
你需要这样的东西(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>
验证这一点:
<?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>
答案 2 :(得分:1)
替换的另一个例子。
XSD
<?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="abExtension"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="abExtension" type="abExtensionType"/>
<xs:complexType name="abExtensionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="a"/>
<xs:element name="b"/>
</xs:choice>
</xs:complexType>
<xs:element name="abcExtension" substitutionGroup="abExtension">
<xs:complexType>
<xs:complexContent>
<xs:extension base="abExtensionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="c"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="abcdExtension" substitutionGroup="abExtension">
<xs:complexType>
<xs:complexContent>
<xs:extension base="abExtensionType">
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="c"/>
<xs:element name="d"/>
</xs:choice>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
使用此验证的示例XML
abcExtension.xml
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test.xsd">
<abcExtension>
<b></b>
<a></a>
<c></c>
</abcExtension>
</root>
abcdExtension.xml
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test.xsd">
<abcdExtension>
<a>text</a>
<b>test</b>
<d>text</d>
<c>text</c>
</abcdExtension>
</root>
abExtension.xml
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Test.xsd">
<abExtension>
<b></b>
<a></a>
</abExtension>
</root>
答案 3 :(得分:0)
如果您的重点是扩展而非类型继承,则可以通过重新定义<choice>
来扩展<group>
,如下所示:
文件&#34; abc.xsd&#34;包含基本模式:
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="any"
xmlns:n="any"
elementFormDefault="qualified">
<group name="baseGroup">
<choice>
<element name="a"/>
<element name="b"/>
<element name="c"/>
</choice>
</group>
<complexType name="choiceType">
<sequence minOccurs="0" maxOccurs="unbounded">
<group ref="n:baseGroup"/>
</sequence>
</complexType>
<element name="test">
<complexType>
<sequence>
<element name="sample" type="n:choiceType" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>
</schema>
文件&#34; abcdef.xsd&#34;扩展基础架构中定义的<choice>
:
<?xml version="1.0"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="any"
xmlns:n="any"
elementFormDefault="qualified">
<redefine schemaLocation="abc.xsd">
<group name="baseGroup">
<choice>
<group ref="n:baseGroup"/>
<element name="d"/>
<element name="e"/>
</choice>
</group>
</redefine>
</schema>
这将验证以下xml文件,例如:
<?xml version="1.0" encoding="UTF-8"?>
<test
xmlns="any"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="any ../schemas/abcde.xsd">
<sample>
<a/>
<c/>
<b/>
<a/>
</sample>
<sample>
<c/>
</sample>
<sample>
</sample>
<sample>
<a/>
<e/>
<b/>
<d/>
<a/>
</sample>
</test>
答案 4 :(得分:0)
非常简单,您可以使用“选择”关键字并设置其出现次数
<xs:element name="Product">
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs="1" maxOccurs="14">
<xs:element>
</xs:element>
// Post your element configuration here
</xs:choice>
</xs:sequence>
</xs:complexType>