Xquery通过在运行时传递父值来获取子节点

时间:2015-06-17 06:22:32

标签: xpath xquery marklogic

我需要在运行时传递一个值来获取所有的childen元素。

例如,这是我的XML:

<person>
   <details1>
      <name>jack</name>
      <age>26</age>
   </details1>
   <details2>
      <name>john</name>
      <age>48</age>
   </details2>
</person>

我的疑问:

let $y as xs:string := "details1"
let $x := fn:doc(cts:uri-match('*person.xml'))
return $x/$y

所以在这里我期待结果为

<details1>
<name>jack</name>
<age>26</age>
</details1>

但它返回的名称与$ y的名称相同,即“details1”
或者如果我这样查询

let $y as xs:string := "details1"
let $x := fn:doc(cts:uri-match('*person.xml'))
return $x//$y

结果将是“details1”12次

我是XQuery的新手,请帮助我解决问题

3 个答案:

答案 0 :(得分:1)

您似乎尝试使用字符串$y作为节点步骤。但是,在XPath / XQuery中,路径步骤与字符串不同,因此您不能简单地添加字符串作为路径步骤。相反,您可以查找所有后代元素,并要求它们具有相同的名称,即:

let $y as xs:string := "details1"
let $x := fn:doc(cts:uri-match('*person.xml'))
return $x/*[name(.) = $y]

答案 1 :(得分:1)

正如drkk所说,你必须看看元素的名称。但使用name()是危险的。它返回元素的词法名称,如果元素具有前缀,则可能为ns:elem。并且每个文档中的前缀可以不同,即使对于相同的命名空间也是如此。所以要么只匹配本地名称:

let $y as xs:string := 'details1'
let $x := fn:doc(cts:uri-match('*person.xml'))
return
   $x/*[local-name(.) eq $y]

或者更好,匹配QName(请注意node-name()用法):

let $y as xs:string := xs:QName('details1')
let $x := fn:doc(cts:uri-match('*person.xml'))
return
   $x/*[node-name(.) eq $y]

如果元素名称在命名空间内(注意xs:QName()fn:QName()之间的差异):

let $y as xs:string := fn:QName('namespace-uri', 'details1')
let $x := fn:doc(cts:uri-match('*person.xml'))
return
   $x/*[node-name(.) eq $y]

答案 2 :(得分:0)

另一种方法是使用xdmp:value()动态评估XPath:

let $y as xs:string := "details1"
let $x := fn:doc(cts:uri-match('*person.xml'))
return xdmp:value("$x/" || $y)

如果$ x是一个大型数据集,那么通过消除为集合中的每个文档获取元素名称的需要,该方法可以获得性能优势。

有关详细信息,请参阅:

http://docs.marklogic.com/xdmp:value?q=xdmp:value&v=8.0&api=true

希望有帮助,