Reputation: 963
I have a for loop and want to filter some nodes, which works fine:
matches($doc/abc/@def, $filterA)
matches($doc/qwert/@xyz, $filterB)
What also works is, when $filterA
, $filterB
or both are empty, to return every node. What does not work however is to return the node if node abc
or qwert
do not exist. For the default value i currently use ""
(empty string), is there another default value or another function I can use to make it work?
Upvotes: 1
Views: 105
Reputation: 66783
You can test whether the abc
and qwert
elements exist with the fn:exists()
function. If you want it to pass if either of those elements do not exist, you can use fn:not()
to negate a test for abc
and qwert
existence:
fn:not(fn:exists($doc/abc) and fn:exists($doc/qwert))
If you want a condition to pass if either $filterA
or $filterB
is empty:
fn:not(fn:exists($filterA) and fn:exists($filterB))
You can consolidate the matches()
expressions a predicate to avoid repeating $doc
(not a huge savings, but something to think of more generally when writing XPath expressions.
$doc[matches(abc/@def, $filterA) and matches(qwert/@xyz, $filterB)]
Putting it all together:
let $filterA := "a"
let $filterB :="b"
let $doc := <doc><abc def="a"/><qwert xyz="b"/></doc>
return
if (fn:not(fn:exists($doc/abc) and fn:exists($doc/qwert))
or fn:not(fn:exists($filterA) and fn:exists($filterB))
or $doc[matches(abc/@def, $filterA) and matches(qwert/@xyz, $filterB)])
then "pass - copy nodes"
else "fail"
Upvotes: 1