如何使用 xslt 选择第一次出现的节点

D.Q*_*.Q. 5 xslt xpath

我有一个 xml,如下所示:

\n\n
<bookstores>\n    <bookstore>\n        <book id="1">\n            <author>ABC</author> \n        </book>\n        <book id="2">\n            <title>YYY</title> \n        </book>\n    </bookstore>\n    <bookstore>\n        <book id="3">\n            <author>ABC</author> \n        </book>\n        <book id="4">\n            <author>DEF</author> \n        </book>\n    </bookstore>\n    <bookstore>\n        <book id="5">\n            <price>50</price>\n        </book>\n        <book id="6">\n            <title>ZZZ</title> \n        </book>\n    </bookstore>\n</bookstores>\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想选择“book”节点的子节点的第一次出现,或者换句话说,选择“book”节点的所有唯一子节点。

\n\n

所以输出应该是这样的:

\n\n
author\ntitle\nprice\n
Run Code Online (Sandbox Code Playgroud)\n\n

我写了一个xslt:

\n\n
<xsl:for-each select="bookstores/bookstore/book"> \n    <xsl:if test="count(preceding-sibling::*[1]) = 0">\n        <xsl:value-of select="local-name(*[1])"/>\n    </xsl:if>\n</xsl\xef\xbc\x9afor-each>\n
Run Code Online (Sandbox Code Playgroud)\n\n

它没有给我带来任何回报...任何人都可以给我一些帮助吗?谢谢!!

\n\n

更新:

\n\n

如果我的 xml 中有多个“bookstores”元素,并且我只想限制每个“bookstores”上下文中的唯一性,以便即使“author”也出现在一个“bookstores”中,该怎么办,如果出现在其他“书店”中还能显示吗?

\n

Tim*_*m C 3

如果您使用的是 XSLT1.0,则获取不同元素的方法是通过称为 Muenchian 分组的技术。在您的情况下,您希望按书籍子元素“分组”,因此首先定义一个键来按元素名称查找书籍的子元素

 <xsl:key name="child" match="book/*" use="local-name()" />
Run Code Online (Sandbox Code Playgroud)

为了获得不同的名称,您可以查看所有书籍子元素,但仅输出在给定名称的组中第一个出现的元素。你可以使用这个可怕的语句来做到这一点:

<xsl:apply-templates 
   select="//book/*[generate-id() = generate-id(key('child', local-name())[1])]" />
Run Code Online (Sandbox Code Playgroud)

这是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="text"/>
   <xsl:key name="child" match="book/*" use="local-name()" />

   <xsl:template match="/">
      <xsl:apply-templates select="//book/*[generate-id() = generate-id(key('child', local-name())[1])]" />
   </xsl:template>

   <xsl:template match="//book/*">
      <xsl:value-of select="concat(local-name(), '&#10;')" />
   </xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

当应用于您的 XML 时,将输出以下内容

author
title
price
Run Code Online (Sandbox Code Playgroud)