假设我们有这个简单的xml ...
<books>
<book>
<author/>
<title/>
</book>
<book>
<author/>
<title/>
</book>
</books>
我正在使用此xpath来获取第一个图书实例的元素。
//books[1]/*
返回
<author/>
<title/>
这样可以正常工作,但我必须使用local-name()。我尝试过以下但没有一个工作......
//*[local-name()='books']/*
这会返回重复的作者和标题元素,不好,我只需要第一个孩子
//*[local-name()='books'][0]/*
这不会返回任何内容
基本上,我想创建一个CSV文件,因此输出中的第一行将是一个标题,列出书籍属性名称,后跟任意数据值。我只需要让标题部分工作。
author,title
john,The End is Near
sally,Looking for Answers
答案 0 :(得分:12)
这是一个常见问题解答 - XPath []
运算符的优先级(优先级)高于//
伪运算符。
所以:
//someElemName[1]
选择名为someElemName
的每个元素作为其父元素的第一个子元素 - 并且,根据XML文档,可以有多个这样的元素。
要更改此设置,必须使用括号。
使用强>:
(//*[local-name() = 'book'])[1]/*
另请注意:在XPath中,位置是从1开始的,而不是从0开始。
基于XSLT的验证:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select=
"(//*[local-name() = 'book'])[1]/*"/>
</xsl:template>
</xsl:stylesheet>
将此转换应用于以下XML文档:
<books>
<book num="1">
<author num="1"/>
<title num="1"/>
</book>
<book num="2">
<author num="2"/>
<title num="2"/>
</book>
</books>
选择所需节点并将其复制到输出:
<author num="1"/>
<title num="1"/>
答案 1 :(得分:11)
您说的路径表达式适用于您
//books[1]/*
生成任何&lt; books&gt;的第一个(并且仅在这种情况下)出现的所有子节点的列表。节点。因为,在您的数据中,唯一出现的是&lt; books&gt;在根,它与
相同/books/*
返回两个&lt; book&gt;节点,所以说你只返回一个节点就错了。
很难知道您需要什么,就像您始终将local-name
应用于根节点一样,您不需要知道其名称,只需/*
即可访问它,所以你只想
/*/*[1]
但是要访问&lt; books&gt;的第一个子节点您要编写的文档中的任何位置
//*[local-name()='books']/*[1]
您应该小心尽可能地限制您的上下文,因为使用//
启动XPath表达式将强制搜索整个文档,如果有问题的节点总是如此,这将是毫无意义且耗时的在根。
答案 2 :(得分:0)
我必须遇到同样的担忧。我解决了如下:
//*[local-name()='MYNODENAME' and position()=X]
度过愉快的一天。