From this XML source :
<?xml version="1.0" encoding="utf-8" ?>
<ROOT>
<STRUCT>
<COL order="1" nodeName="FOO/BAR" colName="Foo Bar" />
<COL order="2" nodeName="FIZZ" colName="Fizz" />
</STRUCT>
<DATASET>
<DATA>
<FIZZ>testFizz</FIZZ>
<FOO>
<BAR>testBar</BAR>
<LIB>testLib</LIB>
</FOO>
</DATA>
<DATA>
<FIZZ>testFizz2</FIZZ>
<FOO>
<BAR>testBar2</BAR>
<LIB>testLib2</LIB>
</FOO>
</DATA>
</DATASET>
</ROOT>
I want to generate this HTML :
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<tr>
<td>Foo Bar</td>
<td>Fizz</td>
</tr>
<tr>
<td>testBar</td>
<td>testFizz</td>
</tr>
<tr>
<td>testBar2</td>
<td>testFizz2</td>
</tr>
</table>
</body>
</html>
Here is the XSLT I currently have :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/ROOT">
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<tr>
<!--Generate the table header-->
<xsl:apply-templates select="STRUCT/COL">
<xsl:sort data-type="number" select="@order"/>
</xsl:apply-templates>
</tr>
<xsl:apply-templates select="DATASET/DATA" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="COL">
<!--Template for generating the table header-->
<td>
<xsl:value-of select="@colName"/>
</td>
</xsl:template>
<xsl:template match="DATA">
<xsl:variable name="pos" select="position()" />
<tr>
<xsl:for-each select="/ROOT/STRUCT/COL">
<xsl:sort data-type="number" select="@order"/>
<xsl:variable name="elementName" select="@nodeName" />
<td>
<xsl:value-of select="/ROOT/DATASET/DATA[$pos]/*[name() = $elementName]" />
</td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
It almost works, the problem I have is to retrieve the correct DATA node from the path specified in the "nodeName" attribute value of the STRUCT block.
Here is a pure XSLT 1.0 solution that doesn't use any extensions:
<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="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<xsl:apply-templates select="*/STRUCT"/>
<xsl:apply-templates select="*/DATASET/DATA"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="STRUCT">
<tr>
<xsl:apply-templates select="COL"/>
</tr>
</xsl:template>
<xsl:template match="COL">
<td><xsl:value-of select="@colName"/></td>
</xsl:template>
<xsl:template match="DATA">
<tr>
<xsl:apply-templates select="/*/STRUCT/*/@nodeName">
<xsl:with-param name="pCurrentNode" select="."/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="@nodeName" name="getNodeValue">
<xsl:param name="pExpression" select="string(.)"/>
<xsl:param name="pCurrentNode"/>
<xsl:choose>
<xsl:when test="not(contains($pExpression, '/'))">
<td><xsl:value-of select="$pCurrentNode/*[name()=$pExpression]"/></td>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getNodeValue">
<xsl:with-param name="pExpression"
select="substring-after($pExpression, '/')"/>
<xsl:with-param name="pCurrentNode" select=
"$pCurrentNode/*[name()=substring-before($pExpression, '/')]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<ROOT>
<STRUCT>
<COL order="1" nodeName="FOO/BAR" colName="Foo Bar" />
<COL order="2" nodeName="FIZZ" colName="Fizz" />
</STRUCT>
<DATASET>
<DATA>
<FIZZ>testFizz</FIZZ>
<FOO>
<BAR>testBar</BAR>
<LIB>testLib</LIB>
</FOO>
</DATA>
<DATA>
<FIZZ>testFizz2</FIZZ>
<FOO>
<BAR>testBar2</BAR>
<LIB>testLib2</LIB>
</FOO>
</DATA>
</DATASET>
</ROOT>
the wanted, correct result is produced:
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<tr>
<td>Foo Bar</td>
<td>Fizz</td>
</tr>
<tr>
<td>testBar</td>
<td>testFizz</td>
</tr>
<tr>
<td>testBar2</td>
<td>testFizz2</td>
</tr>
</table>
</body>
</html>
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