Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove whitespace from HTML generated using XSL

Background

Maintain readable XSL source code while generating HTML without excessive breaks that introduce spaces between sentences and their terminating punctuation. From Rethinking XSLT:

White space in XSLT stylesheets is especially problematic because it serves two purposes: (1) for formatting the XSLT stylesheet itself; and (2) for specifying where whitespace should go in the output of XSLT-processed XML data.

Problem

An XSL template contains the following code:

  <xsl:if test="@min-time &lt; @max-time">
    for
    <xsl:value-of select="@min-time" />
    to
    <xsl:value-of select="@max-time" />
    minutes
  </xsl:if>

  <xsl:if test="@setting">
    on <xsl:value-of select="@setting" /> heat
  </xsl:if>
  .

This, for example, generates the following output (with whitespace exactly as shown):

    for
    2
    to
    3
    minutes
  .

All major browsers produce:

for 2 to 3 minutes .

Nearly flawless, except for the space between the word minutes and the punctuation. The desired output is:

for 2 to 3 minutes.

It might be possible to eliminate the space by removing the indentation and newlines within the XSL template, but that means having ugly XSL source code.

Workaround

Initially the desired output was wrapped in a variable and then written out as follows:

<xsl:value-of select="normalize-space($step)" />.

This worked until I tried to wrap <span> elements into the variable. The <span> elements never appeared within the generated HTML code. Nor is the following code correct:

<xsl:copy-of select="normalize-space($step)" />.

Technical Details

The stylesheet already uses:

<xsl:strip-space elements="*" />
<xsl:output indent="no" ... />

Related

  • Storing html tags within an xsl variable

Question

How do you tell the XSLT processor to eliminate that space?

Thank you!

like image 589
Dave Jarvis Avatar asked Apr 20 '26 09:04

Dave Jarvis


1 Answers

Instead of using copy-of you can apply the identity template with an additional template that trims the spaces from the text nodes. You only create one variable like in your first workaround.

You call:

<li><xsl:apply-templates select="$step" mode="nospace" />.</li>

The templates:

<xsl:template match="text()" mode="nospace" priority="1" >
    <xsl:value-of select="normalize-space(.)" />
</xsl:template>

<xsl:template match="node() | @*" mode="nospace">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" mode="nospace" />
    </xsl:copy>
</xsl:template>
like image 156
user570783 Avatar answered Apr 25 '26 11:04

user570783