我有一个xml文档,如下所示:
<Output>
<Integer start="0 0 0 0 0 0 0"/>
<Dimensions>
<Dimension value="2"/>
<Dimension value="3"/>
</Dimensions>
</Output>
我还有一个XSD文件,它定义了相应的结构。 start属性定义为整数列表。 在此XSD文件中,我希望有一个断言,该断言检查此列表中的值的数量是否等于Dimension元素的所有值属性的乘积。在这种情况下,必须在开始时定义2 * 3 = 6个值。
类似于
<xs:assert test="count(data(./Integer/@start)) = multiply(./Dimensions/Dimension/@value) "/>
我的问题是如何将乘法写成类似于sum,但是用乘法而不是加法。是否可以向XSD文档添加功能?还是有可能重写断言测试以满足我的要求?
答案 0 :(得分:1)
XSD 1.1断言仅限于XPath 2.0,这使这一工作变得困难。无法访问XPath 3.1 fold-left()
函数或用户定义的函数(这将允许递归)。
某些XSD 1.1处理器可能会解除此限制(您可以将Saxon配置为允许XPath 3.1),但这超出了规范。
如果您准备限制“尺寸”的数量,则可以这样做
number(if (exists(Dimension[1])) then Dimension[1]/@value else 1) *
number(if (exists(Dimension[2])) then Dimension[2]/@value else 1) *
number(if (exists(Dimension[3])) then Dimension[3]/@value else 1) *
... etc
但是我认为没有使用纯XSD 1.1 + XPath 2.0的通用解决方案。
启用XPath 3.1后,您可以
count(...) = fold-left(Dimension/@value, 1,
function($total, $next){$total*number($next)})
答案 1 :(得分:0)
如果我对您的理解正确,那么您正在请求可用于列表/序列的乘法功能。
由于没有这样的内置函数afaik,因此需要这样的用户定义的递归函数(在XQuery的功能编程领域):
declare function local:rec-multiply($seq, $count) {
if(empty($seq)) then ()
else
let $prod := $seq[1],
$count := $count * $prod
return (
<count>{ $count }</count>,
local:rec-multiply($seq[position() > 1], $count)
)
};
count(tokenize(//Integer/@start, '\s'))
= local:rec-multiply(//Dimension/@value, 1)[last()]
注意事项:此代码需要XQuery 3+,并且常见的XSD处理器仅支持XPath 2.0(实际上通常仅支持子集)。如果您解除了这种限制,那么也可以使用XQuery的fold-left / right函数,如Michael Kay所述。
但是,最后,最简单的方法是提取这些值并以通用编程语言执行乘法和验证。