xsl-list
[Top] [All Lists]

RE: nodes or multiple runs?

2004-02-12 02:13:09

On another point you were asking, recreating a transform chain in a 
single stylesheet is very easy, much easier than writing the chain 
imho, so you should have no problem there.


I'm not sure what you mean by "recreating a transform chain 
in a single stylesheet." 

Do you mean something like this:

<xsl:template match = "/">
  <xsl:variable name = "phase1">
    <xsl:apply-templates select = "." mode = "phase1"/>
  </xsl:variable>
  <xsl:appy-templates select = "$phase1" mode = "phase2"/> 
</xsl:template>

?

If I understand things correctly, I can use this method and 
still maintain the logic of my stylesheets, only having to 
use mode for evry template.

The idea is to do each processing stage in a variable with each stage
operating on the last variable.

So, if you had some xml and you wanted to find the average of the two
percentages, such as:

<root>
  <node>25%</node>
  <node>75%</node>
</root>


You can only sum() across a node-set, but here you would need to remove
the '%' first for sum() to work.  You can do that first stage in a
variable:

<xsl:variable name="first">
  <xsl:for-each select="/root/node">
    <node number_without_percent="{translate(.,'%','')}"/>
  </xsl:for-each>
</xsl:variable>

This variable would then hold a result-tree-fragment (RTF or temporary
tree) which would look like:

<node number_without_percent="25"/>
<node number_without_percent="75"/>

Now you can use sum(), div and count to work out the mean average.
First you need to change the context node you are working on to the
variable.  And of course, to perfom operations on a RTF in xslt 1.0, you
will need to convert it to a node-set first using your processors
node-set extension function.

The variable code would now look like:

<xsl:variable name="first-rtf">
  <xsl:for-each select="/root/node">
    <node number_without_percent="{translate(.,'%','')}"/>
  </xsl:for-each>
</xsl:variable> 
<xsl:variable name="first" select="exsl:node-set($first-rtf)"/>

Notice name change to original variable name.  This allows me to use my
name-of-choice on the node-set.

Now we can perform operations on the node-set.  First change the context
node to that of the node-set, this is done using for-each.

 <xsl:for-each select="$first">
  ...
 </xsl:for-each>

The node-set '$first' in now effectively the input document for the code
contained within the for each.  The find the average you need to sum()
the values together, divide them by the total number of nodes, and then
concatenate a percent sign on the end:

 <xsl:value-of select="concat(sum(node/@number_without_percent)
                       div
                       count(node),
                       '%')"/>


The whole stylesheet would look as follows.  If you output each variable
at each stage, its very easy to keep track of whats going on. 

<xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
     xmlns:exsl="http://exslt.org/common";>

<xsl:variable name="first-rtf">
  <xsl:for-each select="/root/node">
    <node number_without_percent="{translate(.,'%','')}"/>
  </xsl:for-each>
</xsl:variable>
<xsl:variable name="first" select="exsl:node-set($first-rtf)"/>

<xsl:template match="/">

  <nodeset><xsl:copy-of select="$first"/></nodeset>

  <xsl:for-each select="$first">
    <xsl:value-of select="concat(sum(node/@number_without_percent)
                          div
                          count(node),
                          '%')"/>
  </xsl:for-each>

</xsl:template>

</xsl:stylesheet>


cheers
andrew

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



<Prev in Thread] Current Thread [Next in Thread>