Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XSLT 1.0 and string counting

So I'm trying to solve a problem in xslt which I would normally know how to do in an imperative language. I'm adding cells to a table from a list of xml elements, standard stuff. So:

<some-elements>
  <element>"the"</element>
  <element>"minds"</element>
  <element>"of"</element>
  <element>"Douglas"</element>
  <element>"Hofstadter"</element>
  <element>"and"</element>
  <element>"Luciano"</element>
  <element>"Berio"</element>
</some-elements>

However, I want to cut off one row and start a new one after a certain character maximum has been reached. So say I allow at the most, 20 characters per row. I'd end up with this:

<table>
 <tr>
  <td>"the"</td>
  <td>"minds"</td>
  <td>"of"</td>
  <td>"Douglas"</td>
 </tr>
 <tr>
  <td>"Hofstadter"</td>
  <td>"and"</td>
  <td>"Luciano"</td>   
 </tr>
 <tr>
  <td>"Berio"</td>
 </tr>
</table>

In an imperative language, I'd append the elements to a row while adding each elements string-count to some mutable variable. When that variable exceeded 20, I'd stop, build a new row, and rerun the whole process (starting at the stopped element) on that row after returning the string-count to zero. However, I can't change variable values in XSLT. This whole stateless, function evaluation thing is throwing me for a loop.

like image 232
Colin Brogan Avatar asked Jan 17 '23 06:01

Colin Brogan


1 Answers

Coming to this forum from xsl-list is like going back 10 years, why does everyone use xslt 1:-)

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

<xsl:output indent="yes"/>

<xsl:template match="some-elements">
 <table>
  <xsl:apply-templates select="element[1]"/>
 </table>
</xsl:template>


<xsl:template match="element">
 <xsl:param name="row"/>
 <xsl:choose>
  <xsl:when test="(string-length($row)+string-length(.))>20
          or
          not(following-sibling::element[1])">
   <tr>
    <xsl:copy-of select="$row"/>
    <xsl:copy-of select="."/>
   </tr>
   <xsl:apply-templates select="following-sibling::element[1]"/>
  </xsl:when>
  <xsl:otherwise>
   <xsl:apply-templates select="following-sibling::element[1]">
    <xsl:with-param name="row">
     <xsl:copy-of select="$row"/>
     <xsl:copy-of select="."/>
    </xsl:with-param>
   </xsl:apply-templates>
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>
</xsl:stylesheet>
like image 157
David Carlisle Avatar answered Jan 24 '23 16:01

David Carlisle