Reputation: 436
I have following xml:
<test>
<TestStruktur>
<TestReference>ID_text_random_uuid</TestReference>
<TestReference>ID_test_random_uuid</TestReference>
<Name>Some name</Name>
</TestStruktur>
<TestStruktur>
<TestReference>ID_test_random_uuid</TestReference>
<TestReference>ID_text_random_uuid</TestReference>
<Name>Some name</Name>
</TestStruktur>
</test>
I need to search for TestReference elements and check if values contain test
string and then return value from the <Name>
element. I've created xquery that does it but it returns two values because the statement is true for two nodes.
Of course this is only a sample xml. I can have a lot of TestStruktur
nodes and even more TestReference
nodes
Here's my xquery:
declare function local:test($doc as node()) as xs:string {
for $test2 in $doc//test/TestStruktur
for $test in $test2/TestReference
return
if(contains($test, 'test')) then
data($test2/Name)
else ()
};
for $doc in collection('Testing')
return local:test($doc)
Is there any way to, for example, break loop when if statement is true?
Upvotes: 1
Views: 1031
Reputation: 5256
You just filter for the first result:
declare function local:test($doc as node()) as xs:string {
(
for $test2 in $doc//test/TestStruktur
for $test in $test2/TestReference
return
if(contains($test, 'test')) then
data($test2/Name)
else ()
)[1]
};
The predicate might be a case for a quantifier:
declare function local:test($doc as node()) as xs:string
{
(
for $test2 in $doc//test/TestStruktur
where some $test in $test2/TestReference satisfies contains($test, 'test')
return $test2/Name
)
[1]
};
But it could as well be done in a single path expression:
declare function local:test($doc as node()) as xs:string
{
($doc//test/TestStruktur[TestReference[contains(., 'test')]]/Name)[1]
};
All of the above are equivalent. Note that the result type might better be xs:string?
, to provide for the case of no 'test'
being found.
Upvotes: 1
Reputation: 6229
You can limit the returned results to the first node:
(for $test2 in $doc//test/TestStruktur
for $test in $test2/TestReference
where contains($test, 'test')
return data($test2/Name)
)[position() = 1]
This solution may look expensive at first glance, but many XQuery implementation stop looping as soon as the first result has been found.
Upvotes: 2