我有一个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
结尾,我不知道是否它是appleValue
,bananaValue
等,除了我可以查看type
属性并构建字符串。
let $type := (doc("data.xml")/data/item)[1]/@type
doc("data.xml")/data/item/$typeValue
...最后一行是我想要的,显然这不正确但我需要找到基于变量知道名称的元素(存储在$type
之类的变量中)和“价值”。
有什么想法吗?我意识到这个变量元素的命名是奇怪的/奇怪的/坏的......但这就是它的方式,我必须处理它。
答案 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()
函数会为每个答案提供不同的答案(分别为appleValue
,x:appleValue
和y: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]