0

I'm trying to transform an XML table from a larger project into an HTML table, and I'm pretty new to this XSLT game. I've found a lot of material, but I haven't seen anything that's quite like this problem so I thought I'd ask:

<table name="my table (2 columns)">
  <!-- some column headers -->
  <colhddef colnum="1">This is column 1</colhddef>
  <colhddef colnum="2">This is column 2</colhddef>
  <entry row="1" colnum="1">entry 1</entry>
  <entry row="1" colnum="2">entry 2</entry>
  <entry row="2" colnum="1">entry 3</entry>
  <entry row="2" colnum="2">entry 4</entry>
  <entry row="3" colnum="1">entry 5</entry>
  <entry row="3" colnum="2">entry 6</entry>
  <entry row="4" colnum="1">entry 7</entry>
  <entry row="4" colnum="2">entry 8</entry>
</table>

I'm looking to wrap each set of entries with common row attributes with <tr></tr> and it wouldn't hurt to make sure that the columns are placed in the table appropriately. This is probably much simpler than I'm making it... but any help is much appreciated!

Bonus points: where can I find good quality learning resources for XSLT? Recommended books? etc?

Thanks again in advance!

  • As for learning, see the resources section at the end of http://stackoverflow.com/tags/xslt/info. – Martin Honnen Feb 14 '17 at 16:47
  • As for not having found something similar, today http://stackoverflow.com/questions/42228190/how-do-i-sort-a-list-of-xml-items-into-rows-for-an-html-table seems to be the same requirement with slightly different format so try to adapt that, if you are stuck post your attempt. – Martin Honnen Feb 14 '17 at 16:49

1 Answers1

0

This might get you started:

<xsl:template match="table">
 <table>
  <xsl:apply-templates select="entry[@colnum='1']"/>
 </table>
</xsl:template>

<xsl:template match="entry[@colnum='1']">
 <xsl:param name='row'><xsl:value-of select='@row'/></xsl:param>
 <tr>
  <td><xsl:value-of select="."/></td>
  <xsl:apply-templates select="../entry[@row=$row][@colnum!=1]"/>
 </tr>
</xsl:template>

<xsl:template match="entry[@colnum!='1']">
 <td><xsl:value-of select="."/></td>
</xsl:template>

The first template creates a <table></table>, and populates it selecting only the <entry colnum='1'/> nodes from the table node.

The second template sets a parameter $row to the value row attribute of the <entry colnum='1'/> node. It then creates a <tr></tr> container, and adds a <td></td> node containing this entry's text. Finally, it selects entry nodes from the parent table where the row attribute match the $row parameter, and the colnum attribute is not 1.

The last template turns these selected <entry> nodes, with a colnum attribute that is not 1, into a <td></td> node.

Output:

<table>
  <tr>
    <td>entry 1</td>
    <td>entry 2</td>
  </tr>
  <tr>
    <td>entry 3</td>
    <td>entry 4</td>
  </tr>
  <tr>
    <td>entry 5</td>
    <td>entry 6</td>
  </tr>
  <tr>
    <td>entry 7</td>
    <td>entry 8</td>
  </tr>
</table>
AJNeufeld
  • 8,526
  • 1
  • 25
  • 44
  • Thank you! I see I need to get better using the functional programming style for this project. The XML file I need to parse is quite large, and it's easy for the XSLT to get out of control and disorganized. This is much cleaner than my for-each attempts. – pattersonpatterson Feb 16 '17 at 20:00