“这些元素中的任何一个或多个,但必须至少是一个”的 XML 模式构造
Posted
技术标签:
【中文标题】“这些元素中的任何一个或多个,但必须至少是一个”的 XML 模式构造【英文标题】:XML schema construct for "any one or more of these elements but must be at least one" 【发布时间】:2010-09-11 03:26:11 【问题描述】:我正在尝试设置类似于“序列”的架构的一部分,其中所有子元素都是可选的,但至少有一个元素必须存在,并且可能还有更多比其中之一。
我尝试执行以下操作,但 XMLSpy 抱怨“内容模型包含无法唯一确定的元素
<xs:choice>
<xs:sequence>
<xs:element name="DateConstant"/>
<xs:element name="TimeConstant"/>
</xs:sequence>
<xs:element name="DateConstant"/>
<xs:element name="TimeConstant"/>
</xs:choice>
这可以做到吗(如果可以,如何做到)?
一些澄清: 我只想允许同名的每个元素之一。可以有一个“DateConstant”和/或一个“TimeConstant”,但不能有两个。 Gizmo 的答案符合我的要求,但对于大量元素来说是不切实际的。 赫斯特的回答允许两个或多个同名元素,这是我不想要的。
【问题讨论】:
【参考方案1】:试试这个:
<xs:choice>
<xs:sequence>
<xs:element name="Elem1" />
<xs:element name="Elem2" minOccurs="0" />
<xs:element name="Elem3" minOccurs="0" />
</xs:sequence>
<xs:sequence>
<xs:element name="Elem2" />
<xs:element name="Elem3" minOccurs="0" />
</xs:sequence>
<xs:element name="Elem3" />
</xs:choice>
这样做,您强制选择第一个元素,然后选择其余元素,或者第二个元素,其余部分是可选元素,或者第三个元素。
我希望这应该做你想做的事。
当然,您可以将子序列分组,以避免如果您意识到自己错过了一个元素,则在每个序列中重复一个元素。
【讨论】:
考虑到一个很容易有几十个元素需要数百个序列元素来表示这些排列,这真的是一种好习惯吗?【参考方案2】:根据 MSDN 上标题为 Understanding XML Schema 的技术文章 在http://msdn.microsoft.com/en-us/library/aa468557.aspx#understandxsd_topic5 您可以在选择定义(合成器)本身上利用诸如 minOccurs 之类的约束:
“在合成器上使用出现约束适用于整个组”
(请参阅使用嵌套复杂类型的更复杂的示例和 AuthorType 示例)
您将您的要求表述为“必须存在至少一个元素,并且可能存在多个元素”。因此,我建议您尝试以下方法:
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="DateConstant" type="..."/>
<xs:element name="TimeConstant" type="..."/>
</xs:choice>
【讨论】:
这不起作用。如果一个元素不存在,而一个元素存在,则不会有任何错误。【参考方案3】:@hurst,
很遗憾,您未能理解最初的问题。当所有具有 minOccurs="0" 的元素都作为选项包含时,会自动满足将 minOccurs="1" 放在选项上。
因此,您没有考虑原始海报所要求的“至少一个”,因为没有元素正确满足两个完全可选元素的 1 次出现。
到目前为止,我无法找到解决方案,因为 minOccur/maxOccur 都与定义它们的组有关,并且与节点的总数无关。您也不能多次使用选择元素来定义相同的命名元素,否则它会变得“模棱两可”。我已经看到一些示例使用引用而不是特定类型的元素,但我相信这会使 microsoft XSD 解析器失败。
<xs:choice minOccurs="1" maxOccurs="1">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="Elem1" minOccurs="1" maxOccurs="1" />
<xs:element name="Elem2" minOccurs="0" maxOccurs="1" />
</xs:sequence>
<xs:sequence >
<xs:element name="Elem2" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:choice>
在这里,您可以看到您有第一个序列(必须有 Elem1,但可能有 Elem2 可选),或者您有第二个序列(必须有 Elem2)。
因此,您现在拥有这两个元素中的“任何一个或多个”。当然,当您需要为所有可能的组合提供更多选择时,您拥有的选项越多,这就会越复杂。
【讨论】:
只是一个小问题:它不是“指数级更复杂”,只是二次方。但这很麻烦。我希望有更简单的事情。以上是关于“这些元素中的任何一个或多个,但必须至少是一个”的 XML 模式构造的主要内容,如果未能解决你的问题,请参考以下文章