Re: [xsl] Noob: hmm using nested templates, how do i get the nodes within

Subject: Re: [xsl] Noob: hmm using nested templates, how do i get the nodes within
From: "Barry van Weldam" <barry@xxxxxxx>
Date: Tue, 23 Sep 2003 15:58:11 +0200
Thnks Wendell,

For your explanation, gonna read it a couple of times and read up on:

"Barry, I suggest you might spend a bit of time researching the XSLT 
 processing model." 

I thought i knew the basics, i am used to parse an xml for a flashed site.

Guess i made the wrong assumptions,

Grtz

----- Original Message ----- 
From: "Wendell Piez" <wapiez@xxxxxxxxxxxxxxxx>
To: <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Sent: Thursday, September 18, 2003 7:07 PM
Subject: Re: [xsl] Noob: hmm using nested templates, how do i get the nodes within 


> Barry,
> 
> Two problems here. One is the one you asked about ... how you pass a node 
> to a named template as a parameter. The other is that either you haven't 
> quite understood the notion of a "context node" (a critical notion in 
> XSLT), or you haven't explained/described your problem (since it doesn't 
> match your approach).
> 
> The second problem is the deeper one, and if we address it the first one 
> will just go away.
> 
> At 04:38 AM 9/18/2003, you wrote:
> >so now i heard i could use nested template, like
> >-------------------------------------------------
> ><xsl:template match="//Row">
> ><fo:table-row>
> ><fo:table-cell border="solid black 1 px" border-collapse="collapse">
> ><fo:block>
> ><xsl:value-of select="TT"/>
> ></fo:block>
> ></fo:table-cell>
> ><xsl:call-template name="cell"/>
> ></fo:table-row>
> ></xsl:template>
> 
> Correct. Calling the "cell" template with no parameters, it nonetheless 
> takes the context node as its context node. So if in your source data you have
> 
> <Row>
>    <aaa>Total</aaa>
>    <TdD>null</TdD>
>    <NA>45678</NA>
>    <FR>45644</FR>
> </Row>
> 
> when you evaluate this (or any) Row, the template above gives you an 
> fo:table-row containing a cell with the value of the Row's TT child (hey! 
> you don't have any! so what do you want in that cell?), followed by 
> whatever the "cell" template does, with the matched node of the calling 
> template (the row) as its context node.
> 
> But when you call the "cell" template
> 
> ><xsl:template name="cell">
> ><fo:table-cell border="solid black 1 px" border-collapse="collapse">
> ><fo:block>
> ><xsl:variable name="cell" select="//Row/[*]"/> <---------------Here's 
> >where i think i go wrong, how do i select the nodes
> 
> Right -- you're stuck. How, from a "Row" (the context node) do you pick 
> each one of the nodes in turn?
> 
> Actually, it can be done, wrapping it all in a for-each -- but this 
> technique isn't actually the most efficient way XSLT offers to address your 
> requirement.
> 
> Better would be not to pick these nodes up from the Row, but to *change* 
> the context node to each of these. This is very simply done by applying its 
> own template to each them, using a match. Then the context node changes by 
> itself:
> 
> <xsl:template match="TdD | NA | FR">
>    <fo:table-cell border="solid black 1 px" border-collapse="collapse">
>      <fo:block>
>      <!-- we don't need to bind any nodes to the variable: rather, the
>           node we're interested in is whatever node we matched:
>           our context node -->
>        <xsl:choose>
>          <xsl:when test="not(self::node() = 'null')">
>             <xsl:value-of select="self::node()"/>
>          </xsl:when>
>        </xsl:choose>
>      </fo:block>
>    </fo:table-cell>
> </xsl:template>
> 
> Which could be simplified and abbreviated to
> 
> <xsl:template match="TdD | NA | FR">
>    <fo:table-cell border="solid black 1 px" border-collapse="collapse">
>      <fo:block>
>        <xsl:value-of select="self::node()[not(.='null')]"/>
>      </fo:block>
>    </fo:table-cell>
> </xsl:template>
> 
> But to call this template for each of those nodes, we need to change our 
> calling template:
> 
> <xsl:template match="Row">
>    <fo:table-row>
>      <fo:table-cell border="solid black 1 px" border-collapse="collapse">
>        <fo:block>
>          <xsl:value-of select="child::TT"/>
>          <!-- whatever that is... I think you mean select="aaa" -->
>        </fo:block>
>      </fo:table-cell>
>      <xsl:apply-templates name="child::TdD | child::NA | child::FR"/>
>    </fo:table-row>
> </xsl:template>
> 
> "TdD | NA | FR" is short for "child::TdD | child::NA | child::FR", just to 
> be perfectly clear.
> 
> Barry, I suggest you might spend a bit of time researching the XSLT 
> processing model. Basically an XSLT processor starts by matching a root 
> node, and is set up by default to traverse down through the tree 
> (depth-first traversal in "document order"), matching templates as it goes. 
> Each of these templates has the opportunity to create nodes in the output, 
> nodes which in each case end up "wrapping" or "containing" the nodes 
> generated by templates "lower" in the tree (its children and descendants). 
> You simply need to match at two levels -- the row (which generates a row, 
> surprisingly) and the item within the row (which generates a cell). The 
> XSLT Processor can take care of this traversal for you, if you let it.
> 
> Note that although this is "natural", there are times when other 
> complications -- such as, one might want two of your three nodes grouped 
> together in a single cell -- make it very useful to do it with a named 
> template after all. Such as
> 
> <xsl:template match="Row">
>    <fo:table-row>
>      <fo:table-cell border="solid black 1 px" border-collapse="collapse">
>        <fo:block>
>          <xsl:value-of select="child::TT"/>
>          <!-- whatever that is... I think you mean select="aaa" -->
>        </fo:block>
>      </fo:table-cell>
>      <xsl:call-template name="cell">
>        <xsl:with-param name="contents" select="TdD | NA"/>
>      </xsl:call-template>
>      <xsl:call-template name="cell">
>        <xsl:with-param name="contents" select="FR"/>
>      </xsl:call-template>
>    </fo:table-row>
> </xsl:template>
> 
> <xsl:template name="cell">
>    <xsl:param name="contents" select="."/>
>    <xsl:variable name="string-value">
>      <xsl:apply-templates select="contents"/>
>    </xsl:variable>
>    <fo:table-cell border="solid black 1 px" border-collapse="collapse">
>      <xsl:for-each select="$contents[not(.='null')">
>        <fo:block>
>          <xsl:value-of select="."/>
>        </fo:block>
>      </xsl:for-each>
>    </fo:table-cell>
> </xsl:template>
> 
> I hope this is helpful. If it's confusing, study up on templates and the 
> processing model.
> 
> Cheers,
> Wendell
> 
> 
> 
> 
> 
> 
> >Any more suggestions.
> >
> >
> >  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 
> ___&&__&_&___&_&__&&&__&_&__&__&&____&&_&___&__&_&&_____&__&__&&_____&_&&_
>      "Thus I make my own use of the telegraph, without consulting
>       the directors, like the sparrows, which I perceive use it
>       extensively for a perch." -- Thoreau
> 
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 


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


Current Thread