0

我正在尝试列出包含某个 id 的子节点的所有节点。

以这个xml为例:

<foo>
  <bar name="hello">
    <baz id="1" />
  </bar>
  <bar name="there">
    <baz id="1" />
    <baz id="2" />
  </bar>
  <bar name="world">
    <baz id="3" />
  </bar>
</foo>

我想出了以下 XSLT 模板,其中包含两个嵌套for-each循环

<xsl:for-each select="/foo/bar/baz">
  <xsl:variable name="id" select="@id" />
    <xsl:value-of select="$id" />
    <ul>
      <xsl:for-each select="/foo/bar/baz">
        <xsl:variable name="local_id" select="@id" />
        <xsl:variable name="bar_name" select="../@name" />

        <xsl:if test="$id = $local_id">
          <li><xsl:value-of select="$bar_name" /></li>
        </xsl:if>

      </xsl:for-each>
    </ul>
</xsl:for-each>

这给出了以下结果

1
- hello
- there
1
- hello
- there
2
- there
3
- world

问题是第一个键/值对是重复的。

4

1 回答 1

1

为了使解决方案保持原样,您可以更改第一个 for-each ,它只考虑第一次出现的 id。

<xsl:for-each select="/foo/bar/baz[not (preceding::baz/@id = @id)] ">

到目前为止,这还不是解决此类“问题”的最佳方案。为了改善这一点,请查看“使用 Muenchian 方法进行分组”(例如,使用 apply-templates 而不是 for-each 是更好的做法。

这是一个基于密钥的解决方案:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes"/>
    <xsl:key name="kBazId" match="bar/baz" use="@id"/>

    <xsl:template match="/" >
        <xsl:for-each select="/foo/bar/baz[count( . | key('kBazId', @id)[1])=1]" >
            <xsl:value-of select="@id" />
            <ul>
                <xsl:apply-templates select="key('kBazId', @id)/.." />
            </ul>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="bar">
        <li>
            <xsl:value-of select="@name"/>
        </li>
    </xsl:template>
</xsl:stylesheet>
于 2013-06-04T18:09:14.943 回答