I recently had the need to output a SELECT HTML element with a list of states. My initial approach was simple where I used <xsl:copy>
…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="com.thebitguru" exclude-result-prefixes="custom"> <xsl:output method="html" omit-xml-declaration="yes"/> <xsl:strip-space elements="*" /> <custom:states> <option value="AL">Alabama</option> <!-- ... --> <option value="WI">Wisconsin</option> <option value="WY">Wyoming</option> </custom:states> <xsl:template match="option"> <xsl:copy> <xsl:if test="@value = $val"> <xsl:attribute name="selected">selected</xsl:attribute> </xsl:if> <xsl:attribute name="value"><xsl:value-of select="@value" /></xsl:attribute> <xsl:value-of select="." /> </xsl:copy> </xsl:template> <xsl:template match="*"> <label for="state">* State:</label> <select name="state" id="state"> <xsl:apply-templates select="document('')/*/custom:states/option" /> </select> </xsl:template> </xsl:stylesheet> |
The problem with this approach was that the option
tags were printing the xml namespaces, even with the exclude-result-prefixes="custom"
specified (because that attribute does not apply to <xsl:copy>
).
1 2 3 4 |
<option value="AL" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="com.thebitguru">Alabama</option> ... <option value="WI" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="com.thebitguru">Wisconsin</option> <option value="WY" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="com.thebitguru">Wyoming</option> |
I didn’t want these namespaces in the output so after some searching and reading through the docs I decided to create new elements using the <xsl:element>
tags instead, especially since the tag that I was copying was very small.
1 2 3 4 5 6 7 8 9 |
<xsl:template match="option"> <xsl:element name="option"> <xsl:if test="@value = $val"> <xsl:attribute name="selected">selected</xsl:attribute> </xsl:if> <xsl:attribute name="value"><xsl:value-of select="@value" /></xsl:attribute> <xsl:value-of select="." /> </xsl:element> </xsl:template> |
There are other ways to accomplish the same thing, e.g. copy-namespaces in XSLT 2.0, but in my case I was stuck with XSLT 1.0.