我需要测试一个节点的3个属性。 问题是我必须为错误的每个属性返回错误,而且我看不出如何轻松实现。
xquery并不十分灵活,因此...无需太多尝试...
for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
return
if ($theHoldingListsField/@AFL != "MANDATORY") then
(
<error id="DPR-CKSEM-DEP-SMF142-2">
<args>
<arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
<arg value="AFL = {$theHoldingListsField/@AFL}"/>
</args>
<location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
</error>
)
else if ($theHoldingListsField/@attitudeIndicator != "MANDATORY") then
(
<error id="DPR-CKSEM-DEP-SMF142-2">
<args>
<arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
<arg value="attitudeIndicator = {$theHoldingListsField/@attitudeIndicator}"/>
</args>
<location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
</error>
)
因此,在此示例中,我希望能够一次触发这3个错误,而不是其中之一(就像现在一样)。 我什至不知道是否有可能...
谢谢!
答案 0 :(得分:4)
首先将重复的代码放入函数中
:declare function local:check($att as attribute()) as element(error)? {
if ($att != "MANDATORY") then (
<error id="DPR-CKSEM-DEP-SMF142-2">
<args>
<arg value="{$att/../ancestor::node()/@id}"/>
<arg value="{name($att)} = {$att}"/>
</args>
<location value="{functx:path-to-node-with-pos($att/..)}"/>
</error>
) else ()
};
然后您的逻辑简化为
for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
return (local:check($theHoldingListsField/@AFL),
local:check($theHoldingListsField/@attitudeIndicator),
...)
答案 1 :(得分:2)
在标准XQuery中,没有if
的{{1}}不存在,因为else
/ if
/ then
是 expression 在每种情况下都必须计算出某个返回值(请参见functional programming)。
如果要在不满足错误条件时返回空序列,则可以针对每个错误分别进行显式操作。然后,您可以将所有零或一元素序列收集为一个,然后将其自动展平:
else
答案 2 :(得分:2)
另一种选择是采用更具功能性的编程方法。
我们可以将您的测试概括为一个在theHoldingListsField
上运行的函数,因为它只有两个不变式,即属性名称($attr-name
)和错误代码($error-id
)。 / p>
我们基本上遍历了要测试的属性(带有错误代码),并在每个属性上调用local:test
函数,例如
declare function local:test($theHoldingListsField, $attr-name, $error-id) {
$theHoldingListsField/@*[local-name() eq $attr-name][. ne "MANDATORY"] !
<error id="{$error-id}">
<args>
<arg value="{$theHoldingListsField/ancestor::node()/@id}"/>
<arg value="{$attr-name} = {.}"/>
</args>
<location value="{functx:path-to-node-with-pos($theHoldingListsField)}"/>
</error>
};
let $tests := (
["AFL", "DPR-CKSEM-DEP-SMF142-2"],
["attitudeIndicator", "DPR-CKSEM-DEP-SMF142-2"]
)
for $theHoldingListsField in //DisplaySettingCol/theDisplaySetting/theHoldingListsFields
let $test-fn := local:test($theHoldingListsField, ?, ?)
return
$tests ! fn:apply($test-fn, .)
上面的示例利用了XQuery 3.1功能,例如数组([]
,部分函数应用程序(?
),简单映射运算符(!
)和高阶运算符。功能(fn:apply
)。我建议从XQuery 3.1 W3C规范中了解这些内容。
也可以将其重写以删除for
,而可以在所有字段(即local:test
)上使用theHoldingListsFields
函数。