I have some XML structured like below:
<report>
<columns>
<column col_id="col_1">Column 1 title</column>
<column col_id="col_2">Column 2 title</column>
<column col_id="col_3">Column 3 title</column>
</columns>
<rows>
<row>
<col_1>Value 1</col_1>
<!-- No col_2 value exists -->
<col_3>value 3</col_3>
</row>
<row>
<col_1>Value 1</col_1>
<col_2>Value 2</col_2>
<col_3>value 3</col_3>
<col_4>Value 4</col_4><!-- Not interested in this value -->
</row>
</rows>
</report>
I want to output this data as a HTML table using XSLT.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes" />
<xsl:template match="Report">
<!-- Get the column names -->
<xsl:variable name="arr_columns" select="./columns/*" />
<div id="example_report" class="report">
<table style="width:100%">
<thead>
<tr class="header">
<!-- Columns first -->
<xsl:for-each select="$arr_columns">
<th><xsl:value-of select="." /></th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<!-- Now the actual data -->
<xsl:for-each select="./rows/row">
<xsl:variable name="row" select="." />
<tr>
<xsl:for-each select="$arr_columns">
<xsl:variable name="col_id" select="./@column_id" />
<td><xsl:value-of select="$row/$col_id" /></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</div>
</xsl:template>
</xsl:stylesheet>
I was hoping that <xsl:value-of select="$row/$col_id" /> would let me select the column based on its name as stored in the col_id variable. However, PHP's XSLTProcessor blows up on it instead and the report fails to render.
PHP Warning: XSLTProcessor::transformToXml(): No stylesheet associated to this object
I've tried outputting just $row (which as expected outputs the entire row as a string), and $row/col_1 (which outputs the contents of col_1 as expected), but trying to access a node based on the value of a variable just doesn't seem to work. If I output the value of $col_id, it displays the name of the node I want to output, so that variable is getting correctly set in the loop.
I'm guessing that it is possible and I'm doing this wrong, but I'm having a hard time finding an example of how to do this correctly. I did find examples that let you select nodes based on attributes, but as you can see the nodes I have don't have attributes, their name indicates what they hold.
Can someone help with writing the correct selector for this case?
For completeness, this is the output I'm hoping to generate :
<table>
<thead>
<tr>
<th>Column 1 title</th>
<th>Column 2 title</th>
<th>Column 3 title</th>
</tr>
</thead>
<tbody>
<tr>
<td>Value 1</td>
<td></td>
<td>value 3</td>
</tr>
<tr>
<td>Value 1</td>
<td>value 2</td>
<td>value 3</td>
</tr>
</tbody>
</table>
<td>each forrowandcolumn?