XSD - 如何允许元素以任意顺序、任意次数出现?

10 浏览
0 Comments

XSD - 如何允许元素以任意顺序、任意次数出现?

我正在尝试创建一个XSD,并且根据以下要求编写定义:\n

    \n

  • 允许指定的子元素出现任意次数(0到无限次)
  • \n

  • 允许子元素以任意顺序出现
  • \n

\n我查找了各种解决方案,例如这个:\n


  
    
      
      
    
  

\n但据我了解,xs:choice仍然只允许选择单个元素。因此,将MaxOccurs设置为unbounded只意味着\"任意一个\"子元素可以出现多次。这正确吗?\n如果上述解决方案不正确,我该如何实现我在需求中所述的内容?\n编辑:如果需求如下,我该怎么办?\n

    \n

  • 元素child1和child2可以出现任意次数(0到无限次)
  • \n

  • 元素可以以任意顺序出现
  • \n

  • 元素child3和child4应该只出现一次。
  • \n

\n例如,\n这个xml是有效的:\n


 value 
 value 
 value 
 value 
 value 
 value 

\n但这个不是有效的(缺少child3)\n


 value 
 value 
 value 
 value 
 value 

0
0 Comments

问题出现的原因是需要在XSD中允许元素以任意顺序出现任意次数。要解决这个问题,可以使用xsd:choice元素和minOccurs="0" maxOccurs="unbounded"属性来实现。在xsd:element元素中定义一个xsd:complexType元素,并在其中使用xsd:sequence元素来包含xsd:choice元素。在xsd:choice元素中列出要允许出现的元素,并使用minOccurs和maxOccurs属性来指定允许出现的次数。此外,还可以不必使用xsd:sequence元素来包裹xsd:choice元素,直接在xsd:element元素中定义xsd:complexType元素也可以实现相同的效果。

0
0 Comments

在你提出的问题中,child1child2可以以任意顺序出现,任意次数。所以这听起来就是你想要的。

如果你只希望其中一个元素出现无限次数,那么无界限定符应该放在元素上:

<xs:element name="foo">
   <xs:complexType>
      <xs:choice maxOccurs="unbounded">
         <xs:element name="child1" type="xs:int" maxOccurs="unbounded"/>
         <xs:element name="child2" type="xs:string" maxOccurs="unbounded"/>
      </xs:choice>
   </xs:complexType>
</xs:element>

基本上是的,我正在寻找元素child1,child2可以以任意顺序出现,任意次数..你在这里提供的答案只适用于单个元素,对吗?或者这也解决了我的要求?

你提问中的模式符合你的要求;我在回答中提供的替代模式是为了单个元素。希望这样能澄清问题!:)

,,感谢澄清,看到修改后的要求..有什么想法吗?

jvtech:你无法用XML模式满足修改后的要求;唯一实现它的方法是如果child3和child4只能出现在最后。在这种情况下,你需要一个包含一个选择和两个元素的序列。

-Djan我也发现它不起作用。尝试在choice元素上添加maxOccurs="unbounded",以允许多个子元素。

0
0 Comments

XSD - 如何允许元素以任意顺序出现任意次数?

在这个问题的附加版本中,似乎仍未得到答案:如何指定在元素的子元素中,必须有一个名为child3,一个名为child4,以及任意数量的名为child1child2,但对子元素出现的顺序没有任何限制。

这是一个直接定义的正则语言,并且您需要的内容模型与定义字符串集的正则表达式同构,其中数字'3'和'4'分别出现一次,数字'1'和'2'可以出现任意次数。如果不清楚如何编写这个正则表达式,可以考虑构建一个用于识别这种语言的有限状态机的类型。它至少有四个不同的状态:

- 初始状态:未看到'3'或'4'

- 中间状态:已经看到'3'但未看到'4'

- 中间状态:已经看到'4'但未看到'3'

- 终止状态:已经看到'3'和'4'

无论自动机处于什么状态,都可以读取'1'和'2',它们不会改变机器的状态。在初始状态下,也将接受'3'或'4';在中间状态下,只接受'4'或'3';在终止状态下,不接受'3'或'4'。如果我们首先定义一个仅包含'3'和'4'的子集的正则表达式,这个正则表达式的结构最容易理解:

(34)|(43)

为了允许在给定位置上出现任意次数的'1'或'2',我们可以插入(1|2)*(或者如果我们的正则表达式语言接受该表示法,则插入[12]*)。将此表达式插入所有可用位置,我们得到:

(1|2)*((3(1|2)*4)|(4(1|2)*3))(1|2)*

将其转换为内容模型很简单。基本结构等同于正则表达式(34)|(43)

<xsd:complexType name="paul0">
  <xsd:choice>
    <xsd:sequence>
      <xsd:element ref="child3"/>
      <xsd:element ref="child4"/>
    </xsd:sequence>
    <xsd:sequence>
      <xsd:element ref="child4"/>
      <xsd:element ref="child3"/>
    </xsd:sequence>
  </xsd:choice>
</xsd:complexType>

插入零个或多个child1child2的选择是简单的:

<xsd:complexType name="paul1">
  <xsd:sequence>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
          <xsd:element ref="child1"/>
          <xsd:element ref="child2"/>
        </xsd:choice>      
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>
    <xsd:choice minOccurs="0" maxOccurs="unbounded">
      <xsd:element ref="child1"/>
      <xsd:element ref="child2"/>
    </xsd:choice>      
  </xsd:sequence>
</xsd:complexType>

如果我们希望减少冗余,可以为重复的child1child2选择定义一个命名组:

<xsd:group name="onetwo">
  <xsd:choice>
    <xsd:element ref="child1"/>
    <xsd:element ref="child2"/>
  </xsd:choice>   
</xsd:group>
<xsd:complexType name="paul2">
  <xsd:sequence>
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:choice>
      <xsd:sequence>
        <xsd:element ref="child3"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child4"/>
      </xsd:sequence>
      <xsd:sequence>
        <xsd:element ref="child4"/>
        <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
        <xsd:element ref="child3"/>
      </xsd:sequence>
    </xsd:choice>  
    <xsd:group ref="onetwo" minOccurs="0" maxOccurs="unbounded"/>
  </xsd:sequence>
</xsd:complexType>

在XSD 1.1中,对于all组的某些限制已经解除,因此可以更简洁地定义此内容模型:

<xsd:complexType name="paul3">
  <xsd:all>
    <xsd:element ref="child1" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child2" minOccurs="0" maxOccurs="unbounded"/>
    <xsd:element ref="child3"/>
    <xsd:element ref="child4"/>      
  </xsd:all>
</xsd:complexType>

但从前面给出的示例中可以看出,这些对于all组的更改实际上并未改变语言的表达能力;它们只是使某些类型的语言定义更简洁。

我喜欢XSD 1.0的xs:all的替代方案。

+1。这是一个很好的答案,应该获得更多的赞。

很棒的答案!我真的喜欢这样的解释。它揭示了实现目标的所有逻辑和推理过程。现在我不仅知道如何解决这个问题,还学到了解决类似问题的新方法。使用有限状态自动机来解释这个问题是一个很好的主意。

Michael,您说“这些对于所有组的更改实际上并没有改变语言的表达能力;它们只是使某些类型的语言定义更简洁”。但是,如果将问题推广到任意数量的子元素,其中一个子元素只能出现一次,另一个子元素可以出现任意次数,XSD 1.0的解决方案会导致组合爆炸,不是吗?而XSD 1.1的解决方案将保持清晰。

ebruchez,是的 - 表达能力,是我使用的术语,并不等同于简洁性紧凑性简洁性可管理性。表达能力只是问:“这个形式体系能够定义这种语言吗?”它不会询问语法的大小,也不会询问某些语法糖是否会使其变小。您提到的组合爆炸意味着处理大型元素集而不使用XSD 1.1对all组的更改会变得非常不愉快,并且对于大的n可能会耗尽内存。这并不意味着它们在原则上变得不可能。

很好的写作,但是元素声明在哪里呢?您必须在选择列表中使用引用来确保实际元素的唯一性,但是在您显示的这个嵌套树中,没有地方可以放置实际元素声明。

,由元素引用指向的元素声明(如常规情况一样)是顶级/全局元素声明。它们将是显示的顶级复杂类型声明的同级。或者,如果更喜欢,可以将所示的元素引用全部替换为本地元素声明。这会导致冗余并增加维护中的错误可能性,但本身并不是禁止的。

M.Sperberg-McQueen,我没有跟随所有细节,但是这是否意味着XSD 1.0可以表达“任意组合的元素A和元素B的任意序列,但至少其中之一”?或者您上面的示例是否限定了元素的顺序,就像我认为的那样?

我不确定您的问题或混淆的本质。我的答案中的四个解决方案中没有限制子元素的顺序,我不知道是什么让您认为有这种限制。至于XSD等效于(a|b)+,它表示任意序列的ab,但至少其中之一,这并不复杂(回复较慢,对此很抱歉)。

0