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

Posted

技术标签:

【中文标题】使用 local-name() 获取 XSLT 中的第一个子节点【英文标题】:Get first child node in XSLT using local-name() 【发布时间】:2011-12-24 21:22:59 【问题描述】:

假设我们有这个简单的 xml ...

 <books>   
    <book>
       <author/>
       <title/>
    </book>
    <book>
       <author/>
       <title/>
    </book>
 </books>

我正在使用这个 xpath 来获取第一个 book 实例的元素。

//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

【问题讨论】:

您的查询//books[1]/* 应该返回两个书籍元素,而不是作者和标题元素。所以有些地方有些混乱。 不,它只返回第一个与我的 Xalan 1.0 XSLT 转换器 是的,那是我在 OP 中的坏处,我使用的是基于 [1] 的,谢谢提供信息 @RaffiM:您是否知道您接受了一个通常不正确的答案这一事实? 【参考方案1】:

你说的路径表达式对你有用

//books[1]/*

生成任何 节点的第一个(并且仅在这种情况下)出现的所有子节点的列表。因为,在您的数据中, 的唯一出现是在根部,它与

相同
/books/*

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

很难知道你需要什么,好像你总是将local-name应用于根节点,那么你不需要知道它的名字,只需/*就可以访问它,所以你想要简单

/*/*[1]

但是,在您要编写的文档中的任何位置访问 节点的第一个子节点

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

您应该尽可能小心地限制上下文,因为以 // 开头的 XPath 表达式将强制搜索整个文档,如果相关节点始终位于根。

【讨论】:

请参阅我在原始帖子上方的编辑,以获取有关我正在尝试完成的工作的更多详细信息,对于缺少更多详细信息,我们深表歉意。我尝试使用 /*/*[1],它打印了两次“作者,标题”,我只需要打印一次。【参考方案2】:

这是一个常见问题解答——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"/>

【讨论】:

@RaffiM:我的回答对你有用吗?【参考方案3】:

我必须遇到同样的问题。我解决了如下:

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

祝你有美好的一天。

【讨论】:

以上是关于使用 local-name() 获取 XSLT 中的第一个子节点的主要内容,如果未能解决你的问题,请参考以下文章

XSLT 3.0 - 无法在 XSLT 3.0 xml-to-json() 中获取对象数组

想要使用 XSLT 从 Xml 属性中获取价值

如何使用 xslt 获取 XML 的属性值和代码作为 html 的值

如何在 XSLT 中使用 XPath 获取元素数组,包括缺失的元素?

获取元素的值并使其成为 XSLT 中属性的值?

SOA 转换中的 XSLT 映射以获取上个月的最大日期