|
Description:
Tokenizes strings into result tree fragments then processes those fragments to produce a table. Works with mozilla 1+ (which allows direct processing of result tree fragments) and with IE6 (with which it uses msxsl:node-set() to enable the fragment processing).
Source: Text Source
---- Test file
<?xml version="1.0"?>
<?xml-stylesheet href="tabulate.xsl" type="text/xsl"?>
<coords>
X value,Y value,Z value
1,3,5
2,1,6
4,5,2
9,3,7
13,7,3
</coords>
----- XSL file (tabulate.xsl)
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:template match="/">
<html>
<body>
<xsl:call-template name="result_table">
<xsl:with-param name="result_nodes" select="/coords"/>
</xsl:call-template>
</body>
</html>
</xsl:template>
<xsl:template name="result_table">
<xsl:param name="result_nodes"/>
<xsl:variable name="results">
<xsl:call-template name="split-string">
<xsl:with-param name="all">
<text>
<xsl:value-of select="normalize-space(translate($result_nodes,' ','_'))"/>
</text>
</xsl:with-param>
<xsl:with-param name="seperator" select="' '"/>
</xsl:call-template>
</xsl:variable>
<table border="1">
<xsl:choose>
<xsl:when test="function-available('msxsl:node-set')">
<xsl:variable name="results_index_star" select="msxsl:node-set($results)/index/*"/>
<xsl:call-template name="make_rows">
<xsl:with-param name="rows" select="$results_index_star"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="make_rows">
<xsl:with-param name="rows" select="$results/index/*"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</table>
</xsl:template>
<xsl:template name="make_rows">
<xsl:param name="rows"/>
<xsl:for-each select="$rows">
<xsl:variable name="results_row">
<xsl:call-template name="split-string">
<xsl:with-param name="all">
<text>
<xsl:value-of select="."/>
</text>
</xsl:with-param>
<xsl:with-param name="seperator" select="','"/>
</xsl:call-template>
</xsl:variable>
<tr>
<xsl:choose>
<xsl:when test="function-available('msxsl:node-set')">
<xsl:variable name="results_row_index_star" select="msxsl:node-set($results_row)/index/*"/>
<xsl:call-template name="make_a_row">
<xsl:with-param name="row" select="$results_row_index_star"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="make_a_row">
<xsl:with-param name="row" select="$results_row/index/*"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:for-each>
</xsl:template>
<xsl:template name="make_a_row">
<xsl:param name="row"/>
<xsl:for-each select="$row">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</xsl:template>
<xsl:template name="split-string">
<xsl:param name="all"/>
<xsl:param name="seperator"/>
<xsl:choose>
<xsl:when test="function-available('msxsl:node-set')">
<xsl:variable name="all_text" select="msxsl:node-set($all)/text"/>
<xsl:variable name="all_index_star" select="msxsl:node-set($all)/index/*"/>
<xsl:call-template name="split-string-impl">
<xsl:with-param name="all" select="$all"/>
<xsl:with-param name="seperator" select="$seperator"/>
<xsl:with-param name="all_text" select="$all_text"/>
<xsl:with-param name="all_index_star" select="$all_index_star"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="all_text" select="$all/text"/>
<xsl:variable name="all_index_star" select="$all/index/*"/>
<xsl:call-template name="split-string-impl">
<xsl:with-param name="all" select="$all"/>
<xsl:with-param name="seperator" select="$seperator"/>
<xsl:with-param name="all_text" select="$all_text"/>
<xsl:with-param name="all_index_star" select="$all_index_star"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="split-string-impl">
<xsl:param name="all"/>
<xsl:param name="seperator"/>
<xsl:param name="all_text"/>
<xsl:param name="all_index_star"/>
<xsl:variable name="first" select="substring-before($all_text,$seperator)"/>
<xsl:choose>
<xsl:when test="$first or substring-after($all_text,$seperator)">
<xsl:call-template name="split-string">
<xsl:with-param name="all">
<text>
<xsl:value-of select="substring-after($all_text,$seperator)"/>
</text>
<index>
<xsl:copy-of select="$all_index_star"/>
<xsl:text>
</xsl:text>
<w>
<xsl:value-of select="$first"/>
</w>
</index>
</xsl:with-param>
<xsl:with-param name="seperator" select="$seperator"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<index>
<xsl:copy-of select="$all_index_star"/>
<xsl:text>
</xsl:text>
<w>
<xsl:value-of select="$all_text"/>
</w>
</index>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
The license for this recipe is available here.
Discussion:
Issues:
For processing the result tree fragment it has a fall-through to directly accessing the result tree fragment which is illegal according to version 1 of the XSL spec (but is allowed in the unfinished version 2 of the spec). This works for Mozilla, don't know about other browsers.
|