我有一个XML,它可以包含任何元素,例如:
<AnyElements>
<Any1 id="any1" />
<Any2 id="any2" />
...
</AnyElements>
但id
属性是强制性的。
我如何定义这样的xsd?
<xs:element name="AnyElements" type="AnyRootType" />
<xs:complexType name="AnyRootType">
<xs:sequence>
<xs:any type="AnyChildType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AnyChildType">
<xs:attribute ref="id" use="required"/>
</xs:complexType>
<xs:attribute name="id" type="xs:string"/>
答案 0 :(得分:0)
这完全取决于您将如何定义处理模型。以下是您需要首先考虑的一些事项。
any
粒子不能用类型约束。它附带一个名为processContents
的属性,可以跳过,宽松,默认为严格。一旦你完全理解它的含义,那么使用 跳过 只是意味着你将无法强制执行你的强制属性 - 处理器就会这样做,“跳过” 。如果您将其设置为 lax ,则仅当描述内容的XSD实际可用时才会处理,否则它将跳过;第三个选项 严格 ,要求描述此额外内容的XSD可用 - 期限。
因此,只有在验证期间描述“any”的XSD可用时,any
粒子才能工作。我想到的选项是一种限制,但它的优点是最接近任何“精神”,因为它不必从特定的基类型派生,或引用一些引用;为此,一个类似于约束你的要求的关键约束:
<xsd:key name="ofid">
<xsd:selector xpath="*"/>
<xsd:field xpath="@id"/>
</xsd:key>
实际上,键使得属性成为必需。缺点可能是每个值也必须是唯一的。也许使用名为id
的属性,它是预期的;如果你希望将模式应用于诸如age
之类的东西,那么它将无效。
如果您认为在运行时可用的XSD是可接受的,那么其他替代方案可能包括使用抽象元素或具有抽象类型的元素。好处是它会带来一种更有纪律的方法(你将从一开始就明确地设置约束),并且不会放置值约束的唯一性。缺点可能是它创建了与另一个描述“合同”的XSD的耦合 - 你的强制属性。
更新:根据您的评论,以下是基于替代组的替代方案。我尽量保留旧的XSD组件名称。
Contract.xsd :这包含合同的组成部分。它基本上描述了你的替换组的负责人;它表示需要id属性。
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="AnyChildType" abstract="true">
<xsd:attribute name="id" use="required"/>
</xsd:complexType>
<xsd:element name="AnyElement" abstract="true" type="AnyChildType"/>
</xsd:schema>
GenericInstance.xsd :它描述了“通用”文档的根目录。它在您定义的根元素的上下文中“合并”您的契约。
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="Contract.xsd"/>
<xsd:element name="AnyElements" type="AnyRootType"/>
<xsd:complexType name="AnyRootType">
<xsd:sequence>
<xsd:element ref="AnyElement" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
SpecificInstance1.xsd :特定合同。
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="Contract.xsd"/>
<xsd:element name="SomeElement1" substitutionGroup="AnyElement">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="AnyChildType">
<xsd:annotation>
<xsd:documentation>Any content goes.</xsd:documentation>
</xsd:annotation>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
SpecificInstance2.xsd :另一个合同(显示不同的创作风格)。
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="Contract.xsd"/>
<xsd:element name="SomeElement2" substitutionGroup="AnyElement" type="SomeElement2Type"/>
<xsd:complexType name="SomeElement2Type">
<xsd:complexContent>
<xsd:extension base="AnyChildType">
<xsd:annotation>
<xsd:documentation>Any content goes.</xsd:documentation>
</xsd:annotation>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
在视觉上,这就是他们联系在一起的方式。您可以看到XSD之间的耦合保持最小。
示例XML,在您的通用实例定义的范围内有效,以及特定的XML。
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<AnyElements xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SomeElement1 id="1"/>
<SomeElement2 id="1"/>
</AnyElements>
如果您仅限于使用一个XSD验证您的XML,则下面只是一个XSD:
<?xml version="1.0" encoding="utf-8" ?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xsd:schema elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:include schemaLocation="GenericInstance.xsd"/>
<xsd:include schemaLocation="SpecificInstance1.xsd"/>
<xsd:include schemaLocation="SpecificInstance2.xsd"/>
</xsd:schema>
我已经在.NET上运行XSD 1.0测试了上述内容;能够在XSD 1.1上运行或在其他XSD处理器中运行特定功能会使我所说的一些内容无效。