Dan Rigsby – Coding Up Style

Developer.Speaker.Blogger

Preserving line breaks in xml while transforming to html with xslt

Posted by Dan Rigsby on January 3rd, 2008

When using xslt to transform xml into html, sometimes it may be desired to keep the line breaks in the text of the xml and convert them into <br/> tags.  For instance, we pipe the output of build and database scripts to xml.  When rendering into html, we want to keep the line breaks or the text looks garbled.  There are many other situations where you might want to preserve line breaks, but bare with me.

Below I have some text copied from an execution of msbuild.  This text is stored directly into a <text> node in the xml:

<text>Microsoft (R) Build Engine Version 3.5.21022.8
[Microsoft .NET Framework, Version 2.0.50727.1433]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 1/2/2008 6:34:50 PM.
Done Building Project "D:\builds\ININ.BCF.sln" (default targets).

Build succeeded.
    0 Warning(s)
    0 Error(s)</text>

A simple xslt to convert this into html might look like this:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/TR/xhtml1/strict">
    <xsl:output method="html"/>

    <xsl:template match="/">
        <xsl:value-of select="/text"/>
    </xsl:template>
</xsl:stylesheet>

The problem with the xslt is that the line breaks aren’t preserved and as a result, the text looks garbled:

Microsoft (R) Build Engine Version 3.5.21022.8 [Microsoft .NET Framework, Version 2.0.50727.1433] Copyright (C) Microsoft Corporation 2007. All rights reserved. Build started 1/2/2008 6:34:50 PM. Done Building Project "D:\builds\ININ.BCF.sln" (default targets). Build succeeded. 0 Warning(s) 0 Error(s)

Here is the same xslt with the inclusion of a PreserveLineBreaks template:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.w3.org/TR/xhtml1/strict">
    <xsl:output method="html"/>

    <xsl:template match="/">
        <xsl:call-template name="PreserveLineBreaks">
            <xsl:with-param name="text" select="/text"/>
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="PreserveLineBreaks">
        <xsl:param name="text"/>
        <xsl:choose>
            <xsl:when test="contains($text,'&#xA;')">
                <xsl:value-of select="substring-before($text,'&#xA;')"/>
                <br/>
                <xsl:call-template name="PreserveLineBreaks">
                    <xsl:with-param name="text">
                        <xsl:value-of select="substring-after($text,'&#xA;')"/>
                    </xsl:with-param>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$text"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

The template preserves line breaks by writing out the text before the line break, adding a <br/> tag, then recursively calling the template again to look for addition line breaks in the remaining text.  This process continues until every line break is essentially replaced with a <br/>.

Microsoft (R) Build Engine Version 3.5.21022.8

[Microsoft .NET Framework, Version 2.0.50727.1433]

Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 1/2/2008 6:34:50 PM.

Done Building Project "D:\builds\ININ.BCF.sln" (default targets).

Build succeeded.

0 Warning(s)

0 Error(s)

This template could even be modified to replace other characters such as tabs depending on your needs.

11 Responses to “Preserving line breaks in xml while transforming to html with xslt”

  1. Mikael Sand Says:

    Thank you soooo much. This really saved my day.

  2. Shrini Viswanathan Says:

    Thanks for the article. The XSL Template worked out nicely for my task.

  3. Pinelopi Kouleri Says:

    Thanks a mil for this!

  4. Andy Poluektov Says:

    Thanx a lot! It really helped me out!

  5. Jim Craig Says:

    Thanks Dan, I’d been looking for a solution to this for ages. It works a treat!

  6. Gene Says:

    Thanks a lot, this is exactly what I was looking for.
    The only thing I would change in the example is to use slightly different names for the text node and the template’s parameter, because it might take some people (ok, me) a few extra seconds to understand name=”text” select=”/text”.
    Thanks again.

  7. Jono Rogers Says:

    Thanks a heap Dan, that problem with xslt had been annoying me all morning! Worked great!

  8. mateus Says:

    great example! i spent all day trying to get line breaks from my xml to show up using xsl! thank you!

  9. Michael O'Hegarty Says:

    Another option is to preserve the formatting using the html tag.
    e.g.

  10. vishal shah Says:

    Thank you so much Dan… You save me :)

  11. Matt Stibbs Says:

    Is it possible to use a similar method to preserve line breaks when output method is ‘text’?

    I have some formatted XML that I am trying to transform to text, but it will not preserve the line breaks in the text output.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>