如何使用变量节点名称获取节点值?

时间:2012-02-03 12:39:02

标签: xpath xquery

我有一个XML文档,如:

<data>
    <item type="apple">
        <misc>something</misc>
        <appleValue>23</appleValue>
        <misc2>something else</misc2>
    </item>
    <item type="banana">
        <bananaValue>47</bananaValue>
        <random>something</random>
    </item>
</data>

我可以使用doc("data.xml")/data/item获取项目,但我需要从以Value结尾的元素中获取文本。所以我想得到“23”和“47”,但我不一定知道元素名称,这意味着我真正知道的是有些元素以Value结尾,我不知道是否它是appleValuebananaValue等,除了我可以查看type属性并构建字符串。

let $type := (doc("data.xml")/data/item)[1]/@type
doc("data.xml")/data/item/$typeValue

...最后一行是我想要的,显然这不正确但我需要找到基于变量知道名称的元素(存储在$type之类的变量中)和“价值”。

有什么想法吗?我意识到这个变量元素的命名是奇怪的/奇怪的/坏的......但这就是它的方式,我必须处理它。

4 个答案:

答案 0 :(得分:2)

我会避免使用name()函数来支持node-name()local-name()。这样做的原因是name()可以根据源中使用的名称空间前缀(以及是否)提供不同的答案。例如,以下三个元素具有相同的确切名称(QName):

<appleValue xmlns="http://example.com"/>
<x:appleValue xmlns:x="http://example.com"/>
<y:appleValue xmlns:y="http://example.com"/>

但是,name()函数会为每个答案提供不同的答案(分别为appleValuex:appleValuey:appleValue。所以你最好通过使用local-name()忽略命名空间(它为上述所有三种情况返回字符串appleValue)或显式指定命名空间(即使它是空的,如Oliver所示) ,使用node-name()(返回正确的QName值,而不是字符串)。在这种情况下,由于您没有使用名称空间(因为即使您稍后添加了名称空间,代码仍然有效),我会稍微赞成使用local-name(),如下所示:

doc("data.xml")/data/item/*['Value' eq substring-after(local-name(),../@type)]

有关避免name()函数(和例外)的原因的详细说明,请参阅"Perils of the name function"

答案 1 :(得分:1)

感谢这篇文章:Can XPath match on parts of an element's name?

doc("data.xml")/data/item/*[ends-with(name(), "Value")]

答案 2 :(得分:1)

您可以使用name()访问节点的名称。 XPath 1.0没有“ends-with”功能,但通过使用substring()string-length() - 1,您可以到达那里。

//item/*[ substring(  name(),  string-length(name() ) - 4  ) = 'Value']

答案 3 :(得分:0)

实现这一目标的更精确方法是

for $item in doc("data.xml")/data/item
let $value-name := fn:QName('', concat($item/@type, 'Value'))
return $item/*[node-name() = $value-name]