我有以下(打算有效)XML:
<Series>
<A>
<id>1</id>
</A>
<B>
<id>1</id>
</B>
<B>
<id>1</id>
</B>
<B>
<id>2</id>
</B>
</Series>
使用XSD 1.1和XPath 2.0,我想断言名为&#34; B&#34;的最大元素数量。共享相同的&#34; id&#34;价值为&#34; A&#34;。具体来说,我想限制名称&#34; B&#34;的元素数量。可以有&#34; id&#34; = 1,特别是2次出现。我不在乎有多少名为B的元素与其他&#34; id&#34;与A&#39; 1&#34;不匹配的值(因此可能有一百万<B><id>2</id></B>
,它仍然会有效。
这是我尝试的XML Schema 1.1强制执行此操作,在assert指令中使用XPath 2.0表达式:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Series" type="series"/>
<xs:complexType name="series">
<xs:sequence>
<xs:element name="A" type="a"/>
<xs:element name="B" type="b" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="a">
<xs:sequence>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
<xs:assert test="count(following-sibling::element(B)[id/text() = ./id/text()]) eq 2"/>
</xs:complexType>
<xs:complexType name="b">
<xs:sequence>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
但是我的断言总是因cvc断言错误消息而失败。如果我试图将断言放宽到<xs:assert test="count(following-sibling::element(B)) ge 1"/>
,它仍然会失败,所以看起来XML Schema 1.1无法处理所有XPath 2.0构造?
一般来说,有没有办法在XML Schema 1.1中对兄弟进行断言?谢谢!
答案 0 :(得分:3)
XML Schema 1.1断言可以处理所有XPath 2.0,但根据规范(section 3.13.4)
1.3从“部分”·模式后验证信息集中,按照[XDM]中的描述构建数据模型实例。 [XDM]实例的根节点由E构成; 数据模型实例仅包含由[attributes],[children]和E的后代构造的节点和节点。
注意:这种结构的结果是试图在断言中引用E的兄弟姐妹或祖先,或者在E本身之外的输入文档的任何部分,将是不成功的。这种尝试引用本身并不是错误,但用于评估它们的数据模型实例不包括E之外的文档任何部分的任何表示,因此不能引用它们。
(我的大胆)。在评估断言时,您只有以托管断言的元素为根的子树,因此如果要在树的不同部分中断言元素之间的关系,则必须将断言放在其共同祖先之一上。
我认为它的设计是这样的,允许验证解析器在解析期间,在相关元素的末尾评估断言,而不是必须等到整个树构建完毕,然后整体评估所有断言。 / p>
答案 1 :(得分:0)
我找到了如何控制允许的兄弟姐妹数量的答案。关键是不要将断言放在兄弟的类型中,而是放在父节点中。断言条款也因此改变为:
every $aid in child::element(A)/id satisfies (count(child::element(B)[child::id = $aid]) le 2)
。至于我最后提出的关于在XSD 1.1中对兄弟进行断言的更一般性的问题,我还没有开始解决这个问题。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Series" type="series"/>
<xs:complexType name="series">
<xs:sequence>
<xs:element name="A" type="a"/>
<xs:element name="B" type="b" maxOccurs="unbounded"/>
</xs:sequence>
<xs:assert test="every $aid in child::element(A)/id satisfies (count(child::element(B)[child::id = $aid]) le 2)"/>
</xs:complexType>
<xs:complexType name="a">
<xs:sequence>
<xs:element name="id" type="xs:string"/
</xs:sequence>
</xs:complexType>
<xs:complexType name="b">
<xs:sequence>
<xs:element name="id" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:schema>