使用 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>
在第三种情况下,明确定义了可能显示为子元素的内容(例如所有三种类型的“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>
我尝试创建这些的联合,但联合仅允许用于 simpleTypes。
我还尝试定义一个整体类型“type_Scope”,它使用 xs:choice 来包含它们。但 xs:choice 将包含 xs:elements,在这种情况下也需要名称:-(
你能告诉我如何处理这个问题吗?
请不要告诉我 XSD 不可能:-( :-(
谢谢
问候 divB
最佳答案
您可能会得到不同的答案,具体取决于您想使用 XSD 1.1 还是 XSD 1.0 来实现此目的;我假设您正在寻找 1.0 解决方案,我将在此处进行描述(我认为 1.1 尚不实用)。
如果您想保留元素名称并更改其内容,唯一的选择是使用 xsi:type。只需使用单个 Scope 元素即可代替选择;使其类型成为复杂类型,并具有名为“Name”的属性。让其他两种类型从此基类型扩展。你就完成了。
注意:我使用基本抽象类型作为一种机制来通知人们其他类型应该进入其中;事实上,即使没有它,通过从一开始就使用 type_Scope_Base,它也能工作。
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 的解决方案,但我会在开放环境中远离类似的解决方案;今天并不是每个人都有兼容的处理器,更不用说规范本身还不是推荐的。
关于xml - XSD:一个元素应允许采用不同的形式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9718507/