My solution: Macros. If XSLT lacks an element to do what you want (creating a text node with a newline, in Gary's case), just invent the feature you need and send your XSLT stylesheet through another XSLT stylesheet to implement it.
BR
Say you have demo.xsl which wants to use
<x:br/>to emit a newline. (In this example, `x' is simply the namespace for our extensions.) Write an additional stylesheet macros.xsl and send the original demo.xsl through the macro stylesheet to generate the actual XSLT source code. A macro template for <x:br> would be as simple as:
<xsl:template match="x:br"> <_xsl:text><xsl:text> </xsl:text></_xsl:text> </xsl:template>In the macro stylesheet, xsl is the namespace of the "macro definition" and _xsl is the namespace of the "macro expansion". (If you care about details, the trick is to use xsl:namespace-alias to make the XSLT processor believe they are different namespaces.)
DOTIMES
For a more interesting example of macro use, suppose we want to repeat our code count times. Doing this kind of iteration involves a recursive template call, which we want to hide. We will define a macro <x:dotimes> that can be used like this:
<x:dotimes var="i" count="3"> <xsl:value-of select="$i"/> </x:dotimes>Our macro stylesheet replaces each use of <x:dotimes> with a template call, and adds a recursive template as a top-level element:
<xsl:template match="xsl:stylesheet"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> <xsl:for-each select="//x:dotimes"> <_xsl:template name="x:dotimes_{generate-id()}"> ... recursive template definition here ... </_xsl:template> </xsl:for-each> </xsl:copy> </xsl:template> <xsl:template match="x:dotimes"> <_xsl:call-template name="x:dotimes_{generate-id()}"> ... parameters elided for brevity ... </_xsl:call-template> </xsl:template>Download the full macros.xsl and demo.xsl to try the example. To run it with xsltproc, use the Makefile in the same directory.