0

I have a blob of text with delimiters that I'd like to format into an HTML table using XSLT 2.0 (saxon). The text blob (param myTable in this example) contains records separated with |c|. After the 6th record it should become a new row. There's also a |r| delimiter I could use.

So I thought I would use tokenize on the column delimiter to insert the html column tags and then use for-each-group to insert the html row tags. However, having only written fairly simple XSLT until this point, I'm struggling on proper usage.

When using the XML below, I get an error saying that for-each-group has to be of type node(), and not xs:string, which is what tokenize is producing.

I suspect I'm approaching this in a fundamentally wrong way, but I'm stuck with using XSLT and this incoming blob. Any advice appreciated!

<xsl:param name="myTable" />
<xsl:param name="tdSeparator" select="'\|c\|'"/>
<xsl:param name="trSeparator" select="'\|r\|'"/>

<xsl:template name="makeTable">
    <xsl:for-each-group select="fn:tokenize($myTable,$tdSeparator)" group-ending-with="*[position() mod 6 = 0]">    
    <tr>
        <xsl:for-each select="current-group()">
            <td><xsl:copy-of select="current()" /></td>
        </xsl:for-each>
    </tr>
</xsl:for-each-group>
</xsl:template>

<xsl:template match="xvar:metric1" xmlns:xvar="http://test.com/xvar/example">

<root>
    <html>
    <HEAD>
    <META content="text/html; charset=us-ascii" />
    </HEAD>
    <body>
        <p><strong>EMAIL HEADER</strong></p>        
        <p><strong>Key0: </strong> <xsl:value-of select="xvar:key0" /></p>
        <p><strong>Value1: </strong> <xsl:value-of select="xvar:value1" /></p>

etc...

    <table>
        <xsl:call-template name="makeTable" /> 
    </table>
N Simpson
  • 47
  • 7

1 Answers1

2

I don't think you need to group anything, you can simply use tokenize twice:

<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">


<xsl:output method="html" indent="yes"/>

<xsl:param name="myTable" as="xs:string">col 1|c|col 2|c|col 3|r|1|c|2|c|3|r|4|c|5|c|6</xsl:param>
<xsl:variable name="rows" as="xs:string*" select="tokenize($myTable, $trSeparator)"/>

<xsl:param name="tdSeparator" select="'\|c\|'"/>
<xsl:param name="trSeparator" select="'\|r\|'"/>

<xsl:template name="makeTable">
  <table>
    <thead>
      <tr>
        <xsl:for-each select="tokenize($rows[1], $tdSeparator)">
          <th>
            <xsl:value-of select="."/>
          </th>
        </xsl:for-each>
      </tr>
    </thead>
    <tbody>
       <xsl:for-each select="$rows[position() gt 1]">
         <tr>
           <xsl:for-each select="tokenize(., $tdSeparator)">
             <td>
               <xsl:value-of select="."/>
             </td>
           </xsl:for-each>
         </tr>
       </xsl:for-each>
     </tbody>
   </table>
</xsl:template>

</xsl:stylesheet>

Output then is

<table>
   <thead>
      <tr>
         <th>col 1</th>
         <th>col 2</th>
         <th>col 3</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>1</td>
         <td>2</td>
         <td>3</td>
      </tr>
      <tr>
         <td>4</td>
         <td>5</td>
         <td>6</td>
      </tr>
   </tbody>
</table>

I have assumed there is a first row with column names but if not then you simply would need to remove that code e.g.

<xsl:stylesheet version="2.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs">


<xsl:output method="html" indent="yes"/>

<xsl:param name="myTable" as="xs:string">1|c|2|c|3|r|4|c|5|c|6</xsl:param>
<xsl:variable name="rows" as="xs:string*" select="tokenize($myTable, $trSeparator)"/>

<xsl:param name="tdSeparator" select="'\|c\|'"/>
<xsl:param name="trSeparator" select="'\|r\|'"/>

<xsl:template name="makeTable">
  <table>
    <tbody>
       <xsl:for-each select="$rows">
         <tr>
           <xsl:for-each select="tokenize(., $tdSeparator)">
             <td>
               <xsl:value-of select="."/>
             </td>
           </xsl:for-each>
         </tr>
       </xsl:for-each>
     </tbody>
   </table>
</xsl:template>

</xsl:stylesheet>
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110