Re: [xsl] for-each question

Subject: Re: [xsl] for-each question
From: Mike Brown <mike@xxxxxxxx>
Date: Mon, 12 Aug 2002 20:02:28 -0600 (MDT)
Holmberg Rick-ra0119 wrote:
> I am new to Xsl and am trying to parse a xml document into a html doc.  I would like to have a heading above several elements but don't want that heading to show up above each element.  I am sure this is simple but I can't seem to quite get it.  Here is what I have.
>  
> If my xml file looks like this
> <?xml version="1.0" encoding="UTF-8"?>
> <test>
> <id>TestId</id>
> <book>ABC123</book>
> <book>ABC456</book>
> <book>ABC789</book>
> </test>
>  
> I would like the html to read
> The Books are:
> ABC123
> ABC456
> ABC789
>  
> My Stylesheet segment is:
>  
> <xsl:stylesheet version="1.0"
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> <xsl:output omit-xml-declaration="yes"/>             
> <xsl:output method="html"/>
>  
> <xsl:template match="/">
>     <xsl:copy>
>       <xsl:apply-templates/>
>     </xsl:copy>
> </xsl:template>
>  
> <xsl:template match="book">
> <I>
> The Books are:
> <xsl:apply-templates select="book" />
> <xsl:apply-templates/>
> </I>
> </xsl:template>
>  
>  
> With this XSL file I am getting the 'The Books are:' printed 3 times.  

That's right. The template that matches a 'book' element is being invoked 3 
times. A built-in template that matches any element is matching on your 'test'
element and proceding on to all its children, which include the 'id' 
element, the three 'book's, and some whitespace-only text nodes in between.

You would do well to read about the processing model used by XSLT, including
the XPath/XSLT data model and how templates are invoked.

Your stylesheet should contain just these templates:

<xsl:template match="test">
  <I>The books are:</I>
  <xsl:apply-templates select="book"/>
</xsl:template>

<xsl:template match="book">
  <xsl:value-of select="."/>
  <xsl:if test="position() &lt; last()">, </xsl:if>
</xsl:template>

What this means is, when processing a 'test' element (which the built-in
templates will lead you to), you want to add an 'I' element to the result
tree, containing 'The books are:', and following that will be the result
of instantiating the best matching templates for each of the 'book' children 
of the 'test' element. And when processing a 'book' element, you want the 
string-value (XPath terminology for the text content) of that element, 
followed by ', ' if the current node is not the last of the nodes that
were selected for processing (in this case, the current 'book' is not the 
last of all the 'book's).

   - Mike
____________________________________________________________________________
  mike j. brown                   |  xml/xslt: http://skew.org/xml/
  denver/boulder, colorado, usa   |  resume: http://skew.org/~mike/resume/

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread