[xsl] Passing document fragments as nodsets

Subject: [xsl] Passing document fragments as nodsets
From: "Simon Kelly" <kelly@xxxxxxxxxx>
Date: Mon, 7 Jul 2003 09:54:17 +0200
Hi all,

I'm having a bit of a struggle with passing a subset of nodes around in a
xsl file. I have extracted a set of nodes that follow a XPath rule where an
attribute is set, and am paaaing this a a parameter to a template.

<xsl:with-param name="image-nodes">
    <xsl:value-of select="xalan:nodeset(.)/image[@position = 'left']" />
</xsl:with-param>

However, the template I call will then call another template, and this new
template will call another. Each template requiring the nodeset. If I just
call the first template as shown above, I still get the following exception.

java.lang.RuntimeException: Can not convert #RTREEFRAG to a NodeList!

And if I then put all of the <xsl:with-param ...> statements, to make a new
nodeset when called I get a nullpointer exception (Although I can track this
down as no xslt details are given).

Any advice on how to pass nodeset in nested, recursive templates would be
most appreciated. (I have included the xsl file. Sorry it's a bit long. It's
the version that still contains the #RTREEFRAG error)

Cheers

Simon.

[XSL-FILE]
<--

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

  <!-- Main template. Creates footer table with left right
       and center sections-->
  <xsl:template match="footer">
    <!-- Get the image-grid-width -->
    <xsl:variable name="image-grid-width">
      <xsl:value-of select="@image-grid-width" />
    </xsl:variable>

    <table>
      <tr>
        <td>
          <xsl:call-template name="footer-left">
            <xsl:with-param name="image-nodes">
              <xsl:value-of select="xalan:nodeset(.)/image[@position =
'left']" />
            </xsl:with-param>
            <xsl:with-param name="text-nodes">
              <xsl:value-of select="xalan:nodeset(.)/text[@position =
'left']" />
            </xsl:with-param>
            <xsl:with-param name="image-grid-width"
select="$image-grid-width" />
          </xsl:call-template>
        </td>
        <td>
          <xsl:call-template name="footer-center">
            <xsl:with-param name="text-nodes">
              <xsl:value-of select="xalan:nodeset(.)/text[@position =
'center']" />
            </xsl:with-param>
          </xsl:call-template>
        </td>
        <td>
          <xsl:call-template name="footer-right">
            <xsl:with-param name="image-nodes">
              <xsl:value-of select="xalan:nodeset(.)/image[@position =
'right']" />
            </xsl:with-param>
            <xsl:with-param name="text-nodes">
              <xsl:value-of select="xalan:nodeset(.)/text[@position =
'right']" />
            </xsl:with-param>
            <xsl:with-param name="image-grid-width"
select="$image-grid-width" />
          </xsl:call-template>
        </td>
      </tr>
    </table>
  </xsl:template>


  <!-- Left footer section: table generating template.-->
  <xsl:template name="footer-left">
    <xsl:param name="image-nodes" select="/.." />
    <xsl:param name="text-nodes" select="/.." />
    <xsl:param name="image-grid-width" select="2" />

    <xsl:variable name="image-node-count">
      <xsl:call-template name="node-counter">
        <xsl:with-param name="node-set" select="$image-nodes" />
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="text-node-count">
      <xsl:call-template name="node-counter">
        <xsl:with-param name="node-set" select="$text-nodes" />
      </xsl:call-template>
    </xsl:variable>

    <table>
      <xsl:if test="$image-node-count &gt; 0">
        <xsl:call-template name="footer-left-image-rows">
          <xsl:with-param name="node-set" select="$image-nodes" />
          <xsl:with-param name="node-count" select="$image-node-count" />
          <xsl:with-param name="image-grid-width" select="$image-grid-width"
/>
          <xsl:with-param name="max-rows" select="ceiling($image-node-count
div $image-grid-width)" />
        </xsl:call-template>
      </xsl:if>
      <xsl:if test="$text-node-count &gt; 0">
        <xsl:call-template name="footer-text-rows">
          <xsl:with-param name="node-set" select="$text-nodes" />
        </xsl:call-template>
      </xsl:if>
    </table>
  </xsl:template>


  <!-- Left footer section: row generating template for images. -->
  <xsl:template name="footer-left-image-rows">
    <xsl:param name="node-set" select="/.." />
    <xsl:param name="node-count" select="0" />
    <xsl:param name="image-grid-width" />
    <xsl:param name="max-rows" select="1" />
    <xsl:param name="current-row" select="0" />
    <xsl:param name="cell-start" select="1" />
    <xsl:param name="cell-end" select="$cell-start + $image-grid-width" />

    <xsl:if test="not($node-set)">
      <xsl:message terminate="yes">
        Template footer-left-image-rows should never
        be called with an empty node-set. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$current-row &lt; $max-rows">
      <tr>
        <xsl:call-template name="footer-left-image-cells">
          <xsl:with-param name="node-set" select="$node-set" />
          <xsl:with-param name="node-count" select="$node-count" />
          <xsl:with-param name="cell-start" select="$cell-start" />
          <xsl:with-param name="cell-end" select="$cell-end" />
        </xsl:call-template>
      </tr>
      <xsl:call-template name="footer-left-image-rows">
        <xsl:with-param name="node-set" select="$node-set" />
        <xsl:with-param name="node-count" select="$node-count" />
        <xsl:with-param name="image-grid-width" select="$image-grid-width"
/>
        <xsl:with-param name="max-rows" select="$max-rows" />
        <xsl:with-param name="current-row" select="$current-row + 1" />
        <xsl:with-param name="cell-start" select="$cell-end"/>
        <xsl:with-param name="cell-end" select="$cell-end +
$image-grid-width" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>


  <!-- Left footer section: cell data generation -->
  <xsl:template name="footer-left-image-cells">
    <xsl:param name="node-set" select="/.." />
    <xsl:param name="node-count" select="0" />
    <xsl:param name="cell-start" select="0" />
    <xsl:param name="cell-end" select="0" />

    <xsl:if test="not($node-set)">
      <xsl:message terminate="yes">
        Template footer-left-image-cells should never
        be called with an empty node-set. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$node-count &lt; 1">
      <xsl:message terminate="yes">
        Template footer-left-image-cells was called without
        a value passed in node-count. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$cell-start &lt; 1">
      <xsl:message terminate="yes">
        Template footer-left-image-cells was called without
        a value passed in cell-start. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$cell-end &lt; 1">
      <xsl:message terminate="yes">
        Template footer-left-image-cells was called without
        a value passed in cell-end. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$cell-start &lt; $cell-end">
      <xsl:choose>
        <xsl:when test="$cell-start &lt; $node-count">
          <td>
            <a href="{node-set[$cell-start]/link}"><img
               src='{node-set[$cell-start]/src}'
               alt='{node-set[$cell-start]/alt}'
               height='{node-set[$cell-start]/height}'/></a>
          </td>
        </xsl:when>
        <xsl:otherwise>
          <td></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:call-template name="footer-let-image-cells">
        <xsl:with-param name="node-set" select="$node-set" />
        <xsl:with-param name="node-count" select="$node-count" />
        <xsl:with-param name="cell-start" select="$cell-start + 1" />
        <xsl:with-param name="cell-end" select="$cell-end" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>


  <!-- Center footer section: table generating template -->
  <xsl:template name="footer-center">
    <xsl:param name="text-nodes" select="/.." />

    <table>
      <xsl:call-template name="footer-text-rows">
        <xsl:with-param name="text-nodes" select="$text-nodes" />
      </xsl:call-template>
    </table>
  </xsl:template>


  <!-- Right footer section: table generation template -->
  <xsl:template name="footer-right">
    <xsl:param name="image-nodes" select="/.." />
    <xsl:param name="text-nodes" select="/.." />
    <xsl:param name="image-grid-width" select="2" />

    <xsl:variable name="image-node-count">
      <xsl:call-template name="node-counter">
        <xsl:with-param name="node-set" select="$image-nodes" />
      </xsl:call-template>
    </xsl:variable>

    <xsl:variable name="text-node-count">
      <xsl:call-template name="node-counter">
        <xsl:with-param name="node-set" select="$text-nodes" />
      </xsl:call-template>
    </xsl:variable>

    <table>
      <xsl:if test="$image-node-count &gt; 0">
        <xsl:call-template name="footer-right-image-rows">
          <xsl:with-param name="node-set" select="$image-nodes" />
          <xsl:with-param name="node-count" select="$image-node-count" />
          <xsl:with-param name="image-grid-width" select="$image-grid-width"
/>
          <xsl:with-param name="max-rows" select="ceiling($image-node-count
div $image-grid-width)" />
        </xsl:call-template>
      </xsl:if>
      <xsl:if test="$text-node-count &gt; 0">
        <xsl:call-template name="footer-text-rows">
          <xsl:with-param name="node-set" select="$text-nodes" />
        </xsl:call-template>
      </xsl:if>
    </table>
  </xsl:template>


  <!-- Right footer section: row generation template for images -->
  <xsl:template name="footer-right-image-rows">
    <xsl:param name="node-set" select="/.." />
    <xsl:param name="node-count" select="0" />
    <xsl:param name="image-grid-width" />
    <xsl:param name="max-rows" select="1" />
    <xsl:param name="current-row" select="0" />
    <xsl:param name="cell-end" select="0" />
    <xsl:param name="cell-start" select="$cell-end + $image-grid-width" />

    <xsl:if test="not($node-set)">
      <xsl:message terminate="yes">
        Template footer-left-image-rows should never
        be called with an empty node-set. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$current-row &lt; $max-rows">
      <tr>
        <xsl:call-template name="footer-right-image-cells">
          <xsl:with-param name="node-set" select="$node-set" />
          <xsl:with-param name="node-count" select="$node-count" />
          <xsl:with-param name="cell-start" select="$cell-start" />
          <xsl:with-param name="cell-end" select="$cell-end" />
        </xsl:call-template>
      </tr>
      <xsl:call-template name="footer-right-image-rows">
        <xsl:with-param name="node-set" select="$node-set" />
        <xsl:with-param name="node-count" select="$node-count" />
        <xsl:with-param name="image-grid-width" select="$image-grid-width"
/>
        <xsl:with-param name="max-rows" select="$max-rows" />
        <xsl:with-param name="current-row" select="$current-row + 1" />
        <xsl:with-param name="cell-end" select="$cell-end +
$image-grid-width" />
        <xsl:with-param name="cell-start" select="$cell-start +
$image-grid-width"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>


  <!-- -->
  <xsl:template name="footer-right-image-cells">
    <xsl:param name="node-set" select="/.." />
    <xsl:param name="node-count" select="0" />
    <xsl:param name="cell-start" select="0" />
    <xsl:param name="cell-end" select="0" />

    <xsl:if test="not($node-set)">
      <xsl:message terminate="yes">
        Template footer-left-image-cells should never
        be called with an empty node-set. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$node-count &lt; 1">
      <xsl:message terminate="yes">
        Template footer-left-image-cells was called without
        a value passed in node-count. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$cell-end &lt; $cell-start">
      <xsl:choose>
        <xsl:when test="$cell-start &lt; $node-count">
          <td>
            <a href=""><img src='' alt='' height=''/></a>
          </td>
        </xsl:when>
        <xsl:otherwise>
          <td></td>
        </xsl:otherwise>
      </xsl:choose>
      <xsl:call-template name="footer-let-image-cells">
        <xsl:with-param name="node-set" select="$node-set" />
        <xsl:with-param name="node-count" select="$node-count" />
        <xsl:with-param name="cell-start" select="$cell-start - 1" />
        <xsl:with-param name="cell-end" select="$cell-end" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>


  <!-- Footer section: row generation template for text -->
  <xsl:template name="footer-text-rows">
    <xsl:param name="text-nodes" select="/.." />
    <xsl:param name="node-count" select="0" />
    <xsl:param name="start" select="1" />
    <xsl:param name="end" select="node-count + 1" />

    <xsl:if test="not($text-nodes)">
      <xsl:message terminate="yes">
        Template footer-text-rows was called without
        a value passed in text-nodes. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$node-count &lt; 1">
      <xsl:message terminate="yes">
        Template footer-text-rows was called without
        a value passed in node-count. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:if test="$start &lt; $end">
      <tr>
        <td>
          <xsl:value-of select="$text-nodes[$start]" />
        </td>
      </tr>
      <xsl:call-template name="footer-text-rows">
        <xsl:with-param name="text-nodes" select="$text-nodes" />
        <xsl:with-param name="node-count" select="$node-count" />
        <xsl:with-param name="start" select="$start + 1" />
        <xsl:with-param name="end" select="$end" />
      </xsl:call-template>
    </xsl:if>
  </xsl:template>


  <!-- Node counter -->
  <xsl:template name="node-counter">
    <xsl:param name="node-set" select="/.." />

    <!-- If the node-set is null, return 0. Else count node-set -->
    <xsl:choose>
      <xsl:when test="not($node-set)">
        <xsl:value-of select="0" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name="count">
          <xsl:call-template name="counter">
            <xsl:with-param name="node-set" select="$node-set" />
            <xsl:with-param name="count" />
          </xsl:call-template>
        </xsl:variable>
        <xsl:value-of select="$count" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- Counter -->
  <xsl:template name="counter">
    <xsl:param name="node-set" select="/.." />
    <xsl:param name="count" select="1" />

    <xsl:if test="not($node-set)">
      <xsl:message terminate="yes">
        The node set param of counter can never be null. Check the code!
      </xsl:message>
    </xsl:if>

    <xsl:choose>
      <xsl:when test="$node-set[$count] = last()">
        <xsl:value-of select="$count" />
      </xsl:when>
      <xsl:otherwise>
        <xsl:call-template name="counter">
          <xsl:with-param name="node-set" select="$node-set" />
          <xsl:with-param name="count" select="$count + 1" />
        </xsl:call-template>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

-->

"I have often wondered how it is that every man loves himself more than all
the rest of men, but yet sets less value on his own opinion of himself than
on the opinion of others." -- Georg Christoph Lichtenberg

Institut fuer
Prozessdatenverarbeitung
und Elektronik,
Forschungszentrum Karlsruhe GmbH,
Postfach 3640,
D-76021 Karlsruhe,
Germany.

Tel: (+49)/7247 82-4042
E-mail : kelly@xxxxxxxxxx


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


Current Thread