如何在不排序选择的情况下扩展选择 complexType? [英] How to extend a choice complexType without sequencing the choice?
问题描述
我有一个名为 abType
的选择 complexType:
I have a choice complexType named 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
节点的元素,例如:
This type can be used to create elements with a
and b
nodes in any order like this for example:
<ab>
<b/>
<a/>
</ab>
现在我想创建一个名为 abcType
的派生类型,以允许节点 a
、b
和 c
以任何顺序.因此,我基于 abType
创建了一个新的 complexType:
Now I want to create a derived type called abcType
to allow the nodes a
, b
and c
in any order. Therefore I created a new complexType based on 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>
之后我创建了一个 abc
节点:
After that I created a abc
node:
<abc>
<c/>
<b/>
<a/>
</abc>
但是这个节点无效!在 c
之后放置任何 a
或 b
均无效.原因是,从基类型派生类型会创建一个隐式序列,尽管这两种类型都是选择.XMLspy 是这样说明的:
But this node is invalid! It is not valid to put any a
or b
after a c
. The reason is, that deriving a type from a base type creates an implicite sequence although both types are choices. XMLspy illustrates it in this way:
这个结果对于选择类型来说是毫无用处的.
This result is quite useless for choice types.
所以我的问题是:如何在不排序选择的情况下扩展选择类型?
这里是完整的 XSD 和重现问题的 XML 测试文件:
Here is the complete XSD and an XML test file to reproduce the problem:
<?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>
推荐答案
很遗憾,答案是否定的,您不能扩展选择合成器.从逻辑上讲,如果 a、b 和 c 之间存在某种关系(如在 Java、.NET 中,一切最终都是对象,您可以在 XSD 中做同样的事情),那么我建议改用替换组(或者,如果您愿意,可以使用基于 xsi:type 的东西).
Unfortunately, the short answer is NO, you can't extend a choice compositor. Logically, if there is some sort of relationship between a, b, and c (as in Java, .NET, everything is ultimately an Object, you could do the same in XSD) then I suggest the use of substitution groups instead (or, if you prefer, something based on xsi:type).
更新一个例子.XSD-1:
UPDATE with an example. The 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 类(例如)将产生向后兼容的代码.
The extensibility is that at a point in time, you may have only a, b and c as members. If you, or a consumer, decide to add something (say a d element), then you simply create another schema that references the old one, with the new element d, and then use that new schema instead. The old XSD file doesn't get touched; generating new JAXB classes (as an example) will result in backward compatible code.
因此,XSD-1 将验证如下内容:
So, XSD-1 will validate something like this:
<?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):
You would need something like this (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>
- 图表显示了新"成员列表,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>
这篇关于如何在不排序选择的情况下扩展选择 complexType?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!