XSLT and newlines

Newline and whitespace

1. Newline problems.
2. Introducing newline characters

1.

Newline problems.

Mike Brown



> I am using xalan for xml to xml transformation. Input xml string
> has some DOS carriage return and/or line feeds introduced by the source
> application.

XML parsers normalize CR+LF to LF, except in attribute values containing a CR written as a numeric character reference like 
. So in XSLT you get only LFs (
) 99.999% of the time.

> The source xml string that I was trying to transform is like 
> (exactly as is, including newlines)
> 
> <!DOCTYPE ABC [
> ...
> ]><ABC>
> ...
> <attr>
> value</attr>
> ...
> </ABC>
>

To better understand what is going on, you should use something that helps you create a more tangible representation of the XPath/XSLT node tree.

XPath tree visualization stylesheets you can apply to the above XML: skew.org, skew.org or cranesoft.com

Software providing XPath tree visualization: topxml.com logilab.org and various XML editors like XML SPY.

In the case of the element named 'attr', its child text node will encapsulate the text (linefeed character) + 'value' no matter what you do, because it is considered signficant in the XPath data model.

If you don't wish to use this text verbatim, you may find that applying the XPath function normalize-space() to the node or string will give you the string you wanted. The normalize-space function takes the "string-value" of its argument, strips leading and trailing whitespace, and collapses intermediate runs of whitespace to a single space character, returning an XPath string object.

> Since I have no way of knowing which elements in the source xml would have
> newlines, would it mean that I will need to have the normalize-space 
> function all over my xsl sheet?

Not necessarily. Whereas you might be used to doing things like <xsl:value-of select="/path/to/some/element"/> and are shuddering at the thought of changing this to <xsl:value-of select="normalize-space(/path/to/some/element)"/>, you could utilize the power of XSLT a bit more and do so-called "push" processing like <xsl:apply-templates select="/path/to/some/element"/> and have the template that matches that type of element do <xsl:apply-templates select="text()"/> or you could go straight to the text node itself like <xsl:apply-templates select="/path/to/some/element/text()"/> .. in either case you could then override the built-in template for text nodes by making it do normalize-space() instead of <xsl:copy/>.

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

2.

Introducing newline characters

David Carlisle



  Do anyone of you know how to enable an item in a table
  to go to next line without using <br/>

Just decide what HTML markup you want, and then get xslt to produce it. XSLT knows _nothing_ about rendering html.

  If you are doing the xsl, if you used
  <xsl:value-of select="'
'"/> in the table, it
  won't works.  It won't go to the next line.

That produces a newline in the html file but if you have an HTML file of

one
two
three

then it will render as one two three

as in html newlines render as a space unless they are in a <pre> element or some equivalent css.

So to get a newline in the output you just need to make a newline in your file (as you have done) together with some markup such as pre or a css class on the table entry and a css rule setting the white space property to preserve newlines, or you need to use markup, either a <br /> or wrap each paragraph in a p or div.