Re: [xsl] Finding Nodes That Match Distinct Node Value

Subject: Re: [xsl] Finding Nodes That Match Distinct Node Value
From: "Darcy Parker" <darcyparker@xxxxxxxxx>
Date: Thu, 8 May 2008 12:10:15 -0400
Hi Trish,

The issue is a context issue.  When you write:
<xsl:for-each select="//Artist[@festival = .]">
the '.' inside the predicate refers to the Artist node being being
filtered with the predicate.
You need to save the current Festival in a variable and use this.

A simplified version of the template that does what I think you want:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:template match="/">
<xsl:for-each select="//Artist/@festival[not(.=preceding::Artist/@festival)]">
	<xsl:value-of select="concat('Festival=',.,'&#xa;')"/>
	<xsl:variable name="CurrentFestival" select="."/>
	<xsl:for-each select="//Artist[@festival = $CurrentFestival]">
		<xsl:value-of select="concat('  Artist=',@name,' Date=',Date,'
Stage=',Stage,'&#xa;')"/>
	</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Output is:
Festival=2007
  Artist=John Doe Date=08/17/07 Stage=Stage Two
  Artist=Jane Doe Date=08/15/07 Stage=Stage Three
  Artist=Dick Doe Date=08/16/07 Stage=Stage One
Festival=2006
  Artist=Sally Doe Date=08/16/06 Stage=Stage Four
  Artist=John Q. Public Date=08/15/06 Stage=Stage One
Festival=2005
  Artist=John Smith Date=08/17/05 Stage=Stage Three
Festival=2004
  Artist=Jane Smith Date=08/17/04 Stage=Stage Four
  Artist=Sally Smith Date=08/16/04 Stage=Somethin' Else
  Artist=Dick Smith Date=08/16/04 Stage=Stage Two

On Thu, May 8, 2008 at 11:50 AM,  <Trish@xxxxxxxxxxxxxx> wrote:
> Hi:
>
>  I want to loop through an xml document and get distinct values from an
>  attribute and then find all sibling nodes that have that attribute
>  value.
>
>  I'm pulling distinct festivals based on @festival within each artist
>  just fine, but then I want to go back and get all of the Artist info per
>  festival. It seems like the code I'm using to do this should work, but
>  it doesn't. I can't change the organization of the xml. I'm trying not
>  to use keys. I only have access to XSL 1.0 for this project. The line I
>  need help with is:
>  <xsl:for-each select="//Artist[@festival = .]">
>
>  I'm guessing that the value of "." is lost because I'm beginning at the
>  top of the document again. I'm certain that one of you has an elegant
>  solution.
>
>  XML fragment (url's removed on purpose):
>
>  <?xml version="1.0" encoding="utf-8" ?>
>  <Festival>
>   <Artist festival="2007" name="John Doe">
>     <Url>http://...</Url>
>     <Date>08/17/07</Date>
>     <Stage>Stage Two</Stage>
>   </Artist>
>   <Artist festival="2007" name="Jane Doe">
>     <Url>http://...</Url>
>     <Date>08/15/07</Date>
>     <Stage>Stage Three</Stage>
>   </Artist>
>   <Artist festival="2007" name="Dick Doe">
>     <Url>http://...</Url>
>     <Date>08/16/07</Date>
>     <Stage>Stage One</Stage>
>   </Artist>
>   <Artist festival="2006" name="Sally Doe">
>     <Url>http://...</Url>
>     <Date>08/16/06</Date>
>     <Stage>Stage Four</Stage>
>   </Artist>
>   <Artist festival="2006" name="John Q. Public">
>     <Url>http://...</Url>
>     <Date>08/15/06</Date>
>     <Stage>Stage One</Stage>
>   </Artist>
>   <Artist festival="2005" name="John Smith">
>     <Url>http://...</Url>
>     <Date>08/17/05</Date>
>     <Stage>Stage Three</Stage>
>   </Artist>
>   <Artist festival="2004" name="Jane Smith">
>     <Url>http://...</Url>
>     <Date>08/17/04</Date>
>     <Stage>Stage Four</Stage>
>   </Artist>
>   <Artist festival="2004" name="Sally Smith">
>     <Url>http://...</Url>
>     <Date>08/16/04</Date>
>     <Stage>Somethin' Else</Stage>
>   </Artist>
>   <Artist festival="2004" name="Dick Smith">
>     <Url>http://...</Url>
>     <Date>08/16/04</Date>
>     <Stage>Stage Two</Stage>
>   </Artist>
>  </Festival>
>
>  Code Excerpt:
>
>  <table align="center" border="0" cellpadding="3" cellspacing="1">
>    <tr align="left" valign="top">
>       <td>artist</td>
>       <td>date</td>
>       <td>stage</td>
>    </tr>
>    <xsl:for-each
>  select="//Artist/@festival[not(.=preceding::Artist/@festival)]">
>       <tr>
>          <td colspan="3">
>             <a name="{.}"></a>
>             <xsl:choose>
>                <xsl:when test=". = '2007'">
>                   2 0 0 7&#160;&#8226;&#160;<a href="#2006">2 0 0
>  6</a>&#160;&#8226;&#160;<a href="#2005">2 0 0 5</a>&#160;&#8226;&#160;<a
>  href="#2004">2 0 0 4</a><br />
>                </xsl:when>
>                <xsl:when test=". = '2006'">
>                   <a href="#2007">2 0 0 7</a>&#160;&#8226;&#160;2 0 0
>  6&#160;&#8226;&#160;<a href="#2005">2 0 0 5</a>&#160;&#8226;&#160;<a
>  href="#2004">2 0 0 4</a><br />
>                </xsl:when>
>                <xsl:when test=". = '2005'">
>                   <a href="#2007">2 0 0 7</a>&#160;&#8226;&#160;<a
>  href="#2006">2 0 0 6</a>&#160;&#8226;&#160;2 0 0 5&#160;&#8226;&#160;<a
>  href="#2004">2 0 0 4</a><br />
>                </xsl:when>
>                <xsl:when test=". = '2004'">
>                   <a href="#2007">2 0 0 7</a>&#160;&#8226;&#160;<a
>  href="#2006">2 0 0 6</a>&#160;&#8226;&#160;<a href="#2005">2 0 0
>  5</a>&#160;&#8226;&#160;2 0 0 4<br />
>                </xsl:when>
>                <xsl:otherwise>
>                   <a href="#2007">2 0 0 7</a>&#160;&#8226;&#160;<a
>  href="#2006">2 0 0 6</a>&#160;&#8226;&#160;<a href="#2005">2 0 0
>  5</a>&#160;&#8226;&#160;<a href="#2004">2 0 0 4</a><br />
>                </xsl:otherwise>
>             </xsl:choose>
>          </td>
>       </tr>
>       <xsl:for-each select="//Artist[@festival = .]">
>          <tr>
>             <td><a href="{Url}"><xsl:value-of select="@name" /></a></td>
>             <td><xsl:value-of select="Date" /></td>
>             <td><xsl:value-of select="Stage" /></td>
>          </tr>
>       </xsl:for-each>
>    </xsl:for-each>
>  </table>
>
>  Thank you so much in advance,
>  Trish

Current Thread