Xsd 这些元素中至少有一个,但有些元素最多只有一个

Xsd 这些元素中至少有一个,但有些元素最多只有一个,xsd,Xsd,我希望我的XSD能够强制一组元素中至少有一个必须存在。有些元素可以无限次出现,有些是有限的 这些元素本身都不是强制性的,但必须至少有一个元素存在 最后,元素可以以任何顺序出现。i、 e.该命令不得强制执行,也不得对文件的处理产生任何影响 我的尝试是: <xs:element name="Root"> <xs:complexType> <xs:choice> <xs:element minOccurs="0" maxOccurs="

我希望我的XSD能够强制一组元素中至少有一个必须存在。有些元素可以无限次出现,有些是有限的

这些元素本身都不是强制性的,但必须至少有一个元素存在

最后,元素可以以任何顺序出现。i、 e.该命令不得强制执行,也不得对文件的处理产生任何影响

我的尝试是:

<xs:element name="Root">
  <xs:complexType>
    <xs:choice>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="A" type="a:a"/>
      <xs:element minOccurs="0" maxOccurs="unbounded" name="B" type="a:a"/>
      <xs:element minOccurs="0" maxOccurs="1" name="C" type="a:a"/>
      <xs:element minOccurs="0" maxOccurs="1" name="D" type="a:a"/>
    </xs:choice>
  </xs:complexType>
</xs:element>

这不太有效,因为它不强制至少存在其中一个元素

因此,在上面的例子中,必须至少有A、B、C或D中的一个。 可以有多个A或B元素,但每个C或D元素只能有一个

因此,以下各项均应有效:

但以下内容不应有效:

  • -必须至少存在一个元素
  • -必须至少存在一个元素
  • -重复
    元素
这是对现有complexType的扩展,这增加了复杂性,但我认为这不会影响任何事情

这可能吗

我尝试将minOccurs=“1”添加到xs:choice元素中。这没有效果,大概是因为选择的每个实例都可以为空


我还尝试过同时使用xs:choice(子元素中没有minOccurs)和xs:sequence(没有C&D节点),但我找不到任何允许两者共存的父元素。

除了允许前两个示例之外,应该是无效的,您显示的内容模型也失败了,因为它不允许使用第三个或第五个应ok示例

到目前为止,捕获您在XSD、RELAXNG或DTD中描述的约束的最简单方法是添加另一个约束并约束顺序。然后,内容模型是(用DTD表示法)
((A+,B*,C?,D)|(B+,C?,D?)|(C,D?)|(D))
。如果A、B、C、D子项的顺序不传递任何信息,这是迄今为止最简单的方法

然而,如果孩子们的顺序确实传达了信息,并且需要自由,那么你就有一个最复杂的任务。不是特别难,但很复杂,有时(特别是对于更复杂的例子)相当乏味

您描述的A、B、C和D儿童的合法序列集是一种常规语言;考虑一下你用来识别它的有限状态自动机可能会有所帮助。基本上,您需要跟踪三位信息:(a)我们是否看到任何子元素?(b) 我们见过C元素吗?(c) 我们见过D元素吗?如果这些是完全独立的,我们需要在FSA中有八个州;因为它们不是,我们只需要五个:

  • 0开始状态(否、否、否)
  • 1已看到一个或多个A或B元素,但未看到C或D(是、否、否)
  • 2已经看到一个C元素,没有D(X,是,否)
  • 3已经看到了D元素,没有C元素
  • 4.我见过C和D
转换表是

  • 0a,B->1;C->2;D->3
  • 1 A,B->1;C->2;D->3
  • 2 A,B->2;C->错误;D->4
  • 3 A,B->3;C->4;D->错误
  • 4a,B->4;C、 D->错误
接受状态为1-4

请注意,一旦我们看到至少一个元素,A和B都不会对自动机的状态产生任何影响。这就提出了一个开始编写内容模型的好方法:暂时忽略a和B,只使用C和D编写内容模型。由于其中一个必须出现,但两者都不能重复,我们可以这样描述C和D元素的合法顺序(同样,用DTD符号表示紧凑性):

允许A和B任意多次出现(但不是在序列的开头)给我们

如果我们从A或B开始,那么As和Bs的初始序列后面可以是与上面序列匹配的任何序列,或者没有。在这种情况下,内容模型将是

((A|B)+, ( (C, (A|B)*, (D, (A|B)*)?)
         | (D, (A|B)*, (C, (A|B)*)?) )? )
把这些放在一起,内容模型作为一个整体就变得

( ( (A|B)+, ( (C, (A|B)*, (D, (A|B)*)?)
            | (D, (A|B)*, (C, (A|B)*)?) )? )
| (C, (A|B)*, (D, (A|B)*)?)
| (D, (A|B)*, (C, (A|B)*)?) )
将其转换为XSD符号很简单

在一些模式语言中,有更方便的(大多数人的意思是:更紧凑)方式来表达这个或相关的内容模型

在Schematron或XSD1.1中,您可以编写断言(使用XPath)来表示

  • 每个孩子都被命名为A、B、C或D
  • 至少有一个孩子
  • 最多有一个名为C的孩子
  • 最多有一个名为D的孩子
在XSD1.1中,您可以使用其子级为A*、B*、C?和D?的all组,并使用至少有一个子级的断言

在Relax NG中,您可以编写一个内容模型,该模型允许空序列,但与使用交织运算符描述的内容模型不同,因此:

(A* & B* & C? & D?)
您可以使用稍微复杂一点的模型强制非空性:

( ((A|B), (A* & B* & C? & D?))
| (C, (A* & B* & D?))
| (D, (A* & B* & C?)) )

哇!谢谢你非常详细的回答。不幸的是,我不熟悉DTD语法,但是如果我假设它有点类似于正则表达式,那么我可以理解这里的内容。只是想澄清一点——在我的例子中,元素的顺序是完全不相关的。订单不应受到任何限制,也不应以任何方式影响文档的处理。父元素本质上是一个混杂的包,它考虑了用所有可能的顺序复制该组的想法。然而,对于4种元素类型来说,这是非常困难的——在我的实际示例中,实际上有5种元素类型,这几乎肯定会增加。因此,这不是一个实用的解决方案-一定需要更通用的解决方案!是的,DTD表示法类似于(常规正则表达式的子集),只是用逗号而不是并置来描述序列
(A* & B* & C? & D?)
( ((A|B), (A* & B* & C? & D?))
| (C, (A* & B* & D?))
| (D, (A* & B* & C?)) )