为什么我不能将 xs:all 放在 xs:sequence 中?
Why can't I put an xs:all inside a xs:sequence?
我对 XML Schema 还是有点陌生,我正在尝试在 Relax NG Compact 中做一些看起来像这样的事情:
test = element test{
element A {text},
element B {text},
(element C {text}? &
element D {text}?)
}
表示在test元素中包含A,然后是B,然后是任意顺序C和D,这两个都是可选的.
按照我的看法,我应该可以简单地说
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="A"/>
<xs:element name="B"/>
<xs:all>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:all>
</xs:sequence>
</xs:complexType>
</xs:element>
但它不允许我将 <xs:all>
放在 <xs:sequence>
中。说
s4s-elt-must-match.1: The content of 'sequence' must match
(annotation?, (element | group | choice | sequence | any)*). A problem
was found starting at: all.
所以我尝试从 <xs:sequence>
中取出 <xs:all>
,如下所示:
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="A" />
<xs:element name="B"/>
</xs:sequence>
<xs:all>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:all>
</xs:complexType>
</xs:element>
但是现在还是不行,说
s4s-elt-invalid-content.1: The content of '#AnonType_test' is invalid. Element 'all' is invalid, misplaced, or occurs too often
所以我很困惑,因为它看起来很简单,但我不知道该怎么做。
你的困惑是可以理解的。问题是XSD设计是不规则的,不规则的设计往往违背我们的预期。
这是一个变通方法,不幸的是,它更冗长,而且对于要排列的大量元素也不切实际:
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="A"/>
<xs:element name="B"/>
<xs:choice minOccurs="0">
<xs:sequence>
<xs:element name="C"/>
<xs:element name="D" minOccurs="0"/>
</xs:sequence>
<xs:sequence>
<xs:element name="D"/>
<xs:element name="C" minOccurs="0"/>
</xs:sequence>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
另一种解决方法是强制排序;允许任何顺序在实践中通常并不重要。
在我看来,设计的原因之一是允许混合顺序无关 (all
) 和顺序相关 (sequence
, choice
, .. .) 模型组会增加 XML 模式验证在算法方面的复杂性,并会给实施者带来更多负担。
但不仅如此,在某些情况下,例如涉及可选元素,它还可能导致在将元素与粒子匹配时出现歧义(即模型组内的元素声明),引入非确定性或实现依赖性,这对于互操作性来说是不可取的。
总的来说,此类限制的好处大于成本。大多数 XML Schema 用户使用 sequence
和 choice
并强制排序(参见 kjhughes 的示例)。
Relax NG(我不熟悉)可能会使用不同的模型来描述元素的内容,并且该模型可能与不同的设计决策兼容。
我对 XML Schema 还是有点陌生,我正在尝试在 Relax NG Compact 中做一些看起来像这样的事情:
test = element test{
element A {text},
element B {text},
(element C {text}? &
element D {text}?)
}
表示在test元素中包含A,然后是B,然后是任意顺序C和D,这两个都是可选的.
按照我的看法,我应该可以简单地说
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="A"/>
<xs:element name="B"/>
<xs:all>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:all>
</xs:sequence>
</xs:complexType>
</xs:element>
但它不允许我将 <xs:all>
放在 <xs:sequence>
中。说
s4s-elt-must-match.1: The content of 'sequence' must match (annotation?, (element | group | choice | sequence | any)*). A problem was found starting at: all.
所以我尝试从 <xs:sequence>
中取出 <xs:all>
,如下所示:
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="A" />
<xs:element name="B"/>
</xs:sequence>
<xs:all>
<xs:element name="C"/>
<xs:element name="D"/>
</xs:all>
</xs:complexType>
</xs:element>
但是现在还是不行,说
s4s-elt-invalid-content.1: The content of '#AnonType_test' is invalid. Element 'all' is invalid, misplaced, or occurs too often
所以我很困惑,因为它看起来很简单,但我不知道该怎么做。
你的困惑是可以理解的。问题是XSD设计是不规则的,不规则的设计往往违背我们的预期。
这是一个变通方法,不幸的是,它更冗长,而且对于要排列的大量元素也不切实际:
<xs:element name="test">
<xs:complexType>
<xs:sequence>
<xs:element name="A"/>
<xs:element name="B"/>
<xs:choice minOccurs="0">
<xs:sequence>
<xs:element name="C"/>
<xs:element name="D" minOccurs="0"/>
</xs:sequence>
<xs:sequence>
<xs:element name="D"/>
<xs:element name="C" minOccurs="0"/>
</xs:sequence>
</xs:choice>
</xs:sequence>
</xs:complexType>
</xs:element>
另一种解决方法是强制排序;允许任何顺序在实践中通常并不重要。
在我看来,设计的原因之一是允许混合顺序无关 (all
) 和顺序相关 (sequence
, choice
, .. .) 模型组会增加 XML 模式验证在算法方面的复杂性,并会给实施者带来更多负担。
但不仅如此,在某些情况下,例如涉及可选元素,它还可能导致在将元素与粒子匹配时出现歧义(即模型组内的元素声明),引入非确定性或实现依赖性,这对于互操作性来说是不可取的。
总的来说,此类限制的好处大于成本。大多数 XML Schema 用户使用 sequence
和 choice
并强制排序(参见 kjhughes 的示例)。
Relax NG(我不熟悉)可能会使用不同的模型来描述元素的内容,并且该模型可能与不同的设计决策兼容。