我需要在运行时传递一个值来获取所有的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的新手,请帮助我解决问题
答案 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
希望有帮助,