Xml 使用local-name()获取XSLT中的第一个子节点

Xml 使用local-name()获取XSLT中的第一个子节点,xml,xslt,xpath,xslt-1.0,xalan,Xml,Xslt,Xpath,Xslt 1.0,Xalan,假设我们有这个简单的xml <books> <book> <author/> <title/> </book> <book> <author/> <title/> </book> </books> 返回 <author/> <title/> 这将返回重复

假设我们有这个简单的xml

 <books>   
    <book>
       <author/>
       <title/>
    </book>
    <book>
       <author/>
       <title/>
    </book>
 </books>
返回

<author/>
<title/>
这将返回重复的author和title元素,这不好,我只需要第一个子元素

//*[local-name()='books'][0]/*
这不会返回任何内容

基本上,我想创建一个CSV文件,因此输出的第一行将是一个标题,列出图书属性名称,后跟任意数据值。我只需要让标题部分的工作

author,title
john,The End is Near
sally,Looking for Answers

您所说的路径表达式适用于您

//books[1]/*
生成任何节点第一次(仅在本例中)出现的所有子节点的列表。因为,在您的数据中,唯一出现的是根,它与

/books/*
它返回两个节点,所以说它只返回一个节点是错误的

很难知道您需要什么,因为如果您总是将
本地名称
应用于根节点,那么您不需要知道它的名称,只需
/*
即可访问它,因此您只需要

/*/*[1]
但是,要访问要编写的文档中任何位置的节点的第一个子节点

//*[local-name()='books']/*[1]

您应该尽可能小心地限制您的上下文,因为以
/
开始XPath表达式将强制搜索整个文档,如果所讨论的节点始终位于根节点,这将是毫无意义和耗时的。

这是一个常见问题解答--XPath
[]
运算符的优先级(优先级)高于
/
伪运算符

因此:

选择父元素的第一个子元素名为
someElemName
,并且根据XML文档的不同,可以有多个这样的元素

要改变这一点,必须使用括号

使用

(//*[local-name() = 'book'])[1]/*
<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"/>
另请注意:在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文档时

(//*[local-name() = 'book'])[1]/*
<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"/>

所需节点被选中并复制到输出中

(//*[local-name() = 'book'])[1]/*
<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"/>

我必须满足同样的担忧。我的解决办法如下:

//*[local-name()='MYNODENAME' and position()=X]

祝您愉快。

您的查询
//books[1]/*
应该返回两个book元素,而不是author和title元素。所以这里有些混乱。不,它只返回我的Xalan 1.0 XSLT transformerYeah的第一个,这是我在OP中的错误,我使用的是基于[1]的,泰铢info@RaffiM:你知道你接受了一个普遍不正确的答案吗?请参阅我在原始帖子中的编辑,了解我试图完成的更多细节,抱歉没有更多细节。我尝试使用/*/*[1],它打印了两次“作者,标题”,我只需要打印一次。@RaffiM:我的答案对你有用吗?