I. XSLT 2.0 Solution
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/"> <xsl:variable name="vStr" select="'a,b,c,d,e'"/> <xsl:for-each select="tokenize($vStr, ',')"> <option value="{.}"><xsl:value-of select="."/></option> </xsl:for-each> </xsl:template> </xsl:stylesheet>
when this conversion is applied to the ant XML document (not used), the desired, correct result is created :
<option value="a">a</option> <option value="b">b</option> <option value="c">c</option> <option value="d">d</option> <option value="e">e</option>
The explanation . Using the standard XPath 2.0 tokenize() function.
II. XSLT 1.0: Using FXSL 1.x str-split-to-words function / template
This is the XSLT 1.0 conversion:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext"> <xsl:import href="strSplit-to-Words.xsl"/> <xsl:output indent="yes" omit-xml-declaration="yes"/> <xsl:template match="/"> <xsl:variable name="vwordNodes"> <xsl:call-template name="str-split-to-words"> <xsl:with-param name="pStr" select="/"/> <xsl:with-param name="pDelimiters" select="', '"/> </xsl:call-template> </xsl:variable> <xsl:apply-templates select= "ext:node-set($vwordNodes)/*"/> </xsl:template> <xsl:template match="word"> <option value="{.}"><xsl:value-of select="."/></option> </xsl:template> </xsl:stylesheet>
when applied to this XML document :
<t>a,b,cd,e</t>
creates the desired, correct result :
<option value="a">a</option> <option value="b">b</option> <option value="c">c</option> <option value="d">d</option> <option value="e">e</option>
Note The pDelimiters parameter (according to him) may contain more than one separator character - in this case we use both ',' and ' ' .
III. XSLT 1.0 solution using a handwritten recursive named template :
This conversion is:
<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="text()" name="tokenize"> <xsl:param name="pText" select="."/> <xsl:param name="pDelim" select="','"/> <xsl:if test="string-length($pText) > 0"> <xsl:variable name="vToken" select= "substring-before(concat($pText,','), ',')"/> <option value="{$vToken}"> <xsl:value-of select="$vToken"/> </option> <xsl:call-template name="tokenize"> <xsl:with-param name="pText" select= "substring-after($pText,',')"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
when applied to this XML document :
<t>a,b,c,d,e</t>
creates the desired, correct result :
<option value="a">a</option> <option value="b">b</option> <option value="c">c</option> <option value="d">d</option> <option value="e">e</option>
IV. Going to the tokenize template in III above as a template / function parameter for processing each token
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://fxsl.sf.net" exclude-result-prefixes="f"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <f:processToken/> <xsl:variable name="vFunc" select= "document('')/*/f:processToken[1]"/> <xsl:template match="text()" name="tokenize"> <xsl:param name="pText" select="."/> <xsl:param name="pDelim" select="','"/> <xsl:param name="pProcessFunc" select="$vFunc"/> <xsl:if test="string-length($pText) > 0"> <xsl:variable name="vToken" select= "substring-before(concat($pText,','), ',')"/> <xsl:apply-templates select="$pProcessFunc"> <xsl:with-param name="arg1" select="$vToken"/> </xsl:apply-templates> <xsl:call-template name="tokenize"> <xsl:with-param name="pText" select= "substring-after($pText,',')"/> </xsl:call-template> </xsl:if> </xsl:template> <xsl:template match="f:processToken"> <xsl:param name="arg1"/> <option value="{$arg1}"> <xsl:value-of select="$arg1"/> </option> </xsl:template> </xsl:stylesheet>
when this conversion is applied to the same XML document as in III, the same desired, correct result is obtained :
<option value="a">a</option> <option value="b">b</option> <option value="c">c</option> <option value="d">d</option> <option value="e">e</option>
Now, if we replace the last template with this :
<xsl:template match="f:processToken"> <xsl:param name="arg1"/> <p> <xsl:value-of select="$arg1"/> </p> </xsl:template>
again the desired result is obtained :
<p>a</p> <p>b</p> <p>c</p> <p>d</p> <p>e</p>