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

3

I have an XML document like:

<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 结尾,我不知道是 appleValue,还是 bananaValue等等。除非我查看type 属性并构建一个字符串。
let $type := (doc("data.xml")/data/item)[1]/@type
doc("data.xml")/data/item/$typeValue

我试图表达的是最后一行,显然那不正确,但我需要查找元素,这些元素的名称基于一个变量(存储在像$type这样的变量中)和“Value”。

有什么想法吗?我意识到这种变量元素命名方式很奇怪/不寻常/糟糕...但这就是现实,我必须处理它。

4个回答

3

我建议使用node-name()local-name()代替name()函数。原因是name()函数在源中使用什么(以及是否)命名空间前缀可能会给出不同的答案。例如,以下三个元素具有完全相同的名称(QName):

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

然而,对于每一个变量(appleValuex:appleValuey:appleValue),name()函数会给出不同的答案。因此,最好要么通过使用local-name()来忽略命名空间(该函数对上述三种情况都返回字符串appleValue),要么明确指定命名空间(即使它是空的,就像Oliver所示),使用node-name()(该函数返回一个正确的QName值,而不是一个字符串)。在这种情况下,由于您没有使用命名空间(即使以后添加了也可以正常工作),我会略微倾向于使用如下的local-name()
doc("data.xml")/data/item/*['Value' eq substring-after(local-name(),../@type)]

有关避免使用name()函数的原因(和例外情况)的详细解释,请参见"name函数的危险性"


3

1

您可以使用name()访问节点的名称。XPath 1.0没有“ends-with”函数,但是通过使用substring()string-length() - 1,您可以实现相同的功能。

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

0
一个更精确的实现方式是:
for $item in doc("data.xml")/data/item
let $value-name := fn:QName('', concat($item/@type, 'Value'))
return $item/*[node-name() = $value-name]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接