I am trying to list all the nodes which contains a child node which of a certain id.

Take this example 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>

I've come up with the following XSLT template which contains two nested for-each loops

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

Which gives the following result

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

The problem is that the first key/values pair is duplicated.

有帮助吗?

解决方案

To keep the solution as it is you can change the first for-each that it only consider the first occurrence of an id.

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

This is by far not the best solution for this kind of "problem". To improve this have a look for " Grouping Using the Muenchian Method" (E.g.. And also it is better practice to use apply-templates instead of for-each.

Here a key based solution:

<?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>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top