假设我们有这个简单的xml…
<books>
<book>
<author/>
<title/>
</book>
<book>
<author/>
<title/>
</book>
</books>
我使用这个xpath来获取第一个book实例的元素。
//books[1]/*
返回<author/>
<title/>
这工作得很好,但我必须让它使用local-name()工作。我试过以下方法,但都不起作用…
//*[local-name()='books']/*
返回重复的author和title元素,不太好,我只需要它们来自第一个子元素
//*[local-name()='books'][0]/*
这个不返回任何东西
基本上,我想创建一个CSV文件,因此输出中的第一行将是一个标头,列出图书属性名,后跟任意数据值。我只需要让标题部分工作。
author,title
john,The End is Near
sally,Looking for Answers
这是一个常见问题——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"/>
你说的路径表达式为你工作
//books[1]/*
生成第一次出现的所有子节点的列表(在这种情况下是唯一的)节点。因为,在您的数据中,唯一出现的
/books/*
返回两个
很难知道您需要什么,因为如果您总是将local-name
应用于根节点,那么您不需要知道它的名称,并且只需使用/*
即可访问它,因此您只需
/*/*[1]
但是要访问
//*[local-name()='books']/*[1]
您应该小心地尽可能限制上下文,因为以//
开始XPath表达式将强制搜索整个文档,如果所讨论的节点总是在根节点上,那么这是毫无意义且耗时的。
我也有同样的顾虑。我的解决方法如下:
//*[local-name()='MYNODENAME' and position()=X]
祝你今天愉快。