I need to be able to turn a flat xml data sets into html tables, and I'm having trouble finding syntax examples that will fit my need. I would like to use one stylesheet that can convert similar looking data sets into html tables with variable columns. This means it can't use any hard coded element names besides "rows" and "row".
The stylesheet I'm after would be able to convert:
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row>
<AccountId>BlPUAA0</AccountId>
<AccountName>Initech</AccountName>
<AcocuntStatus>Client</AcocuntStatus>
</row>
<row>
<AccountId>CJxIAAW</AccountId>
<AccountName>Intertrode</AccountName>
<AcocuntStatus>Prospect</AcocuntStatus>
</row>
</rows>
into:
<table>
<tr>
<th>AccountId</th>
<th>AccountName</th>
<th>AcocuntStatus</th>
</tr>
<tr>
<td>BlPUAA0</td>
<td>Initech</td>
<td>Client</td>
</tr>
<tr>
<td>CJxIAAW</td>
<td>Intertrode</td>
<td>Client</td>
</tr>
</table>
and this:
<?xml version="1.0" encoding="UTF-8"?>
<rows>
<row>
<AccountId>BlPUAA0</AccountId>
<AccountName>Initech</AccountName>
</row>
<row>
<AccountId>CJxIAAW</AccountId>
<AccountName>Intertrode</AccountName>
</row>
</rows>
into this:
<table>
<tr>
<th>AccountId</th>
<th>AccountName</th>
</tr>
<tr>
<td>BlPUAA0</td>
<td>Initech</td>
</tr>
<tr>
<td>CJxIAAW</td>
<td>Intertrode</td>
</tr>
</table>
Create an XSL stylesheet.xml version=”1.0″?> To bind the XML elements to a HTML table, the <for-each> XSL template must appear before each table row tag. This ensures that a new row is created for each <book> element. The <value-of> template will output the selected text of each child element into a separate table.
The standard way to transform XML data into other formats is by Extensible Stylesheet Language Transformations (XSLT). You can use the built-in XSLTRANSFORM function to convert XML documents into HTML, plain text, or different XML schemas. XSLT uses stylesheets to convert XML into other data formats.
Transform XML to HTMLWrite the Java class to transform the XML file data to HTML using XSLT file. We have put both XML and XSLT files under classpath and finaly transforms the XML data into HTML output. We write the output to the HTML file called books. html under the project's root directory.
Execute an XSLT transformation from an XML fileOpen an XML document in the XML editor. Associate an XSLT style sheet with the XML document. Add an xml-stylesheet processing instruction to the XML document. For example, add the following line to the document prolog: <?
A straight-forward and short solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<table><xsl:apply-templates select="row"/></table>
</xsl:template>
<xsl:template match="row[1]">
<tr><xsl:apply-templates select="*" mode="header"/></tr>
<xsl:call-template name="standardRow"/>
</xsl:template>
<xsl:template match="row" name="standardRow">
<tr><xsl:apply-templates select="*"/></tr>
</xsl:template>
<xsl:template match="row/*">
<td><xsl:apply-templates select="node()"/></td>
</xsl:template>
<xsl:template match="row/*" mode="header">
<th><xsl:value-of select="name()"/></th>
</xsl:template>
</xsl:stylesheet>
when applied on the first provided XML document:
<rows>
<row>
<AccountId>BlPUAA0</AccountId>
<AccountName>Initech</AccountName>
<AcocuntStatus>Client</AcocuntStatus>
</row>
<row>
<AccountId>CJxIAAW</AccountId>
<AccountName>Intertrode</AccountName>
<AcocuntStatus>Prospect</AcocuntStatus>
</row>
</rows>
the wanted, correct result is produced:
<table>
<tr>
<th>AccountId</th>
<th>AccountName</th>
<th>AcocuntStatus</th>
</tr>
<tr>
<td>BlPUAA0</td>
<td>Initech</td>
<td>Client</td>
</tr>
<tr>
<td>CJxIAAW</td>
<td>Intertrode</td>
<td>Prospect</td>
</tr>
</table>
when applied on the second provided XML document:
<rows>
<row>
<AccountId>BlPUAA0</AccountId>
<AccountName>Initech</AccountName>
</row>
<row>
<AccountId>CJxIAAW</AccountId>
<AccountName>Intertrode</AccountName>
</row>
</rows>
again the desired, correct result is produced:
<table>
<tr>
<th>AccountId</th>
<th>AccountName</th>
</tr>
<tr>
<td>BlPUAA0</td>
<td>Initech</td>
</tr>
<tr>
<td>CJxIAAW</td>
<td>Intertrode</td>
</tr>
</table>
I had the urge to try to solve this shortly after posting the question, and here is what I came up with. I guess it makes you wait 24 hours before you can answer it yourself.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<table>
<tr>
<xsl:for-each select="rows/row[1]/*">
<th>
<xsl:value-of select ="local-name()"/>
</th>
</xsl:for-each>
</tr>
<xsl:for-each select="rows/row">
<tr>
<xsl:for-each select="*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table>
<xsl:apply-templates select="rows/row[1]" />
</table>
</xsl:template>
<xsl:template match="row">
<tr>
<xsl:apply-templates mode="th" />
</tr>
<xsl:apply-templates select="../row" mode="td" />
</xsl:template>
<xsl:template match="row/*" mode="th">
<th>
<xsl:value-of select="local-name()" />
</th>
</xsl:template>
<xsl:template match="row" mode="td">
<tr>
<xsl:apply-templates />
</tr>
</xsl:template>
<xsl:template match="row/*">
<td>
<xsl:apply-templates />
</td>
</xsl:template>
</xsl:stylesheet>
Applied to:
<rows>
<row>
<AccountId>BlPUAA0</AccountId>
<AccountName>Initech</AccountName>
<AcocuntStatus>Client</AcocuntStatus>
</row>
<row>
<AccountId>CJxIAAW</AccountId>
<AccountName>Intertrode</AccountName>
<AcocuntStatus>Prospect</AcocuntStatus>
</row>
</rows>
Produces:
<table>
<tr>
<th>AccountId</th>
<th>AccountName</th>
<th>AcocuntStatus</th>
</tr>
<tr>
<td>BlPUAA0</td>
<td>Initech</td>
<td>Client</td>
</tr>
<tr>
<td>CJxIAAW</td>
<td>Intertrode</td>
<td>Prospect</td>
</tr>
</table>
And applied to:
<rows>
<row>
<AccountId>BlPUAA0</AccountId>
<AccountName>Initech</AccountName>
</row>
<row>
<AccountId>CJxIAAW</AccountId>
<AccountName>Intertrode</AccountName>
</row>
</rows>
Produces:
<table>
<tr>
<th>AccountId</th>
<th>AccountName</th>
</tr>
<tr>
<td>BlPUAA0</td>
<td>Initech</td>
</tr>
<tr>
<td>CJxIAAW</td>
<td>Intertrode</td>
</tr>
</table>
Alternatively, this stylesheet produces the same output using a conditional and one fewer template:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table>
<xsl:apply-templates select="rows/row" />
</table>
</xsl:template>
<xsl:template match="row">
<xsl:if test="position()=1">
<tr>
<xsl:apply-templates mode="th" />
</tr>
</xsl:if>
<tr>
<xsl:apply-templates />
</tr>
</xsl:template>
<xsl:template match="row/*" mode="th">
<th>
<xsl:value-of select="local-name()" />
</th>
</xsl:template>
<xsl:template match="row/*">
<td>
<xsl:apply-templates />
</td>
</xsl:template>
</xsl:stylesheet>
Few days ago I post an article, hope it can help you: http://web.swfideas.com/?p=12191
Asuming this data:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Edited by XMLSpy -->
<table-node>
<tbody>
<tr>
<td>[C1R1]</td>
<td>[C2R1]</td>
</tr>
<tr>
<td>[C1R2]</td>
<td>[C2R2]</td>
</tr>
<tr>
<td>[C1R3]</td>
<td>[C2R3]</td>
</tr>
</tbody>
</table-node>
Now, the core, our XSLT template:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Coded by SWFideas -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- table template -->
<xsl:template match="table-node">
<table style="border:solid #000000 1px;border-spacing: 0;border-collapse: collapse;">
<xsl:for-each select="tbody">
<tbody>
<xsl:for-each select="tr">
<tr>
<xsl:for-each select="td">
<td style="border:solid #000000 1px; padding: 5px;">
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</xsl:for-each>
<table>
</xsl:template>
</xsl:stylesheet>
In this first approach I’m avoiding to use COLSPAN and another real-life properties (implementation soon, I promise). So the result if we apply our XSLT will be like this:
<table style="border:solid #000000 1px;border-spacing: 0;border-collapse: collapse;">
<tbody>
<tr>
<td style="border:solid #000000 1px; padding: 5px;">[C1R1]</td>
<td style="border:solid #000000 1px; padding: 5px;">[C2R1]</td>
</tr>
<tr>
<td style="border:solid #000000 1px; padding: 5px;">[C1R2]</td>
<td style="border:solid #000000 1px; padding: 5px;">[C2R2]</td>
</tr>
<tr>
<td style="border:solid #000000 1px; padding: 5px;">[C1R3]</td>
<td style="border:solid #000000 1px; padding: 5px;">[C2R3]</td>
</tr>
</tbody>
</table>
You can try it here: http://www.xsltcake.com/slices/gNfh6i/2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With