[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Conditional counting


Subject: Re: [xsl] Conditional counting
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Fri, 12 Oct 2001 09:29:30 +0100

Hi Peter,

> I've got an XSLt running under LotusXSLt (Xalan) that conditionally calls
> two different extensions:
>
>     <table border="1">
>         <xsl:if test="$gunk = 'x''">
>             <xsl:apply-templates select="myExt.method1(*)" mode="x" />
>         </xsl:if>
>         <xsl:if test="$gunk != 'x'">
>         <xsl:apply-templates select="myExt.method2(*)" mode="x"/>
>         </xsl:if>
>     </table>
>     <xsl:value-of select="count(tr)"/> rows generated.
>
> The returned results will include a varying number of <tr> tags
> (table rows) independent of the passed XML I'd like to have the
> count reflect the number of tr tags returned from the extensions. As
> it is, the count is going to reflect the number of <tr> tags in the
> input XML (zero in our case).
[snip]
> I've tried a couple of differing approaches, in particular with placing the
> extension results into a variable and then parsing the variable and counting
> the tr elements in the variable, but so far no go.

Yes, you could do it like that if you don't mind using the
xalan:nodeSet() extension function. Wrap the xsl:variable around the
section of the code that creates the tr elements:

  <xsl:variable name="rows">
    <xsl:choose>
      <xsl:when test="$gunk = 'x'">
        <xsl:apply-templates select="myExt:method1(*)" mode="x" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="myExt:method2(*)" mode="x" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:variable>

Now you can copy the $rows result tree fragment into the output with:

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

To count the number of tr elements that the result tree fragment
contains, you have to convert the result tree fragment to a node set.
The node set will consist of the root node of the result tree
fragment, so you have to go down to its tr children to get the tr
elements that you want to count:

  count(xalan:nodeSet($rows)/tr)

But I don't think that technique is the best way to do it.
Essentially, the number of rows that you're generating is the same as
the number of nodes returned by whichever of the two extension methods
is used. If you could store those nodes in a variable then you could
first apply templates to them and then count them later on.

The trouble is, of course, that you have different node sets in
different situations. In most cases, you can get around this by
adding predicates to the paths that you're using to access the nodes
(in this case your extension function calls). The predicate holds the
condition in which the nodes from that node set should be retrieved.
In your case, you could do:

  myExt:method1(*)[$gunk = 'x'] | myExt:method2(*)[$gunk != 'x']

If $gunk equals 'x' then only the nodes returned by myExt:method1(*)
are put in the node set; if it doesn't, then the only nodes are the
ones from myExt:method2(*).

Putting that together in your code, you should have something like:

  <table border="1">
    <xsl:variable name="nodes"
                  select="myExt:method1(*)[$gunk = 'x'] |
                          myExt:method2(*)[$gunk != 'x']" />
    <xsl:apply-templates select="$nodes" mode="x" />
  </table>
  <xsl:value-of select="count($nodes)"/> rows generated.

A big caveat on this is that the extension methods that you're using
will both always be evaluated. One downside might be that the process
is less efficient because both methods are called (it depends on how
optimised the processor is, I guess). But a more major downside comes
into play if the condition in the predicate involves testing whether
the extension functions are available or not. For example, if you were
doing:

  myExt:method1(*)[function-available('myExt:method1')] |
  myExt:method2(*)[function-available('myExt:method2')]

then it would fail. But I don't think that's the situation in your
case.

I hope that helps,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


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



Current Thread
Keywords