2015-03-02 79 views
1

我有以下XML:返回第一个值if语句后真

<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,但是它返回两个值,因为该语句对于两个节点是正确的。 当然,这只是一个示例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) 

有没有什么办法,例如,打破循环,如果声明是真实的时候?

回答

2

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

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

该解决方案可以看第一眼昂贵,但很多XQuery实现停止一旦第一个结果发现循环。

+0

+1,但'[position()= 1]'可以缩短为'[1]' – dirkk 2015-03-02 09:52:54

+0

绝对如此。我选择了详细的语法,因为它可以更容易地进行范围测试调整。 – 2015-03-02 11:03:58

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'的情况。