if语句为true后返回第一个值

时间:2015-03-02 08:10:58

标签: xml xquery

我有以下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>

我需要搜索TestReference元素并检查值是否包含test字符串,然后从<Name>元素返回值。我创建了xquery来做它,但它返回两个值,因为两个节点的语句都是true。 当然这只是一个示例xml。我可以有很多TestStruktur个节点甚至更多TestReference个节点

这是我的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)

例如,当if语句为真时,有没有办法打破循环?

2 个答案:

答案 0 :(得分:2)

您可以将返回的结果限制为第一个节点:

(for $test2 in $doc//test/TestStruktur
 for $test in $test2/TestReference
 where contains($test, 'test')
 return data($test2/Name)
)[position() = 1]

乍一看这个解决方案看起来很昂贵,但是一旦找到第一个结果,许多XQuery实现就会停止循环。

答案 1 :(得分:1)

您只需过滤第一个结果:

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]
};

谓词可能是量词的一个例子:

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]
};

但它也可以在单一路径表达式中完成:

declare function local:test($doc as node()) as xs:string
{
  ($doc//test/TestStruktur[TestReference[contains(., 'test')]]/Name)[1]
};

以上所有内容都是等效的。请注意,结果类型最好为xs:string?,以便在没有找到'test'的情况下提供。