using <xsl:preserve-space elements="Client_Comment" /> is preserving font

scm0sml used Ask the Experts™
a snippet of the code im using in an xsl stylesheet is:
<xsl:preserve-space elements="Client_Comment" />
    <xsl:output method="html"/>

and then:
<pre><xsl:value-of select="./@Client_Comment"/></pre>

I have done this to preserve carriage returns etc but it seems to be preserving the font and ignroing my style changes.

Is there anyway around this?
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Gertone (Geert Bormans)Information Architect
Top Expert 2006

Hi scm0sml,
> I have done this to preserve carriage returns

you can't preserve carriage returns in an attribute value.
According to the XML specification,
each XML attribute must be normalized before being sent to the application
Normalisation includes replacing each white-space character with a space
The carriage return is gone before it reaches the XSLT processor

If you want to maintain carriage returns you have to make the string element content



so in english lol?
Information Architect
Top Expert 2006

the XML specification says that a parser must normalize an attribute
before sending it to an application
This means that the parser that gives the parsed XML to the XSLT processor
must do some normalization steps on the attribute value
one of these steps is that every white-space character (tab, carriage return, line-feed, space,...)
will be replaced bay a space
(for a reference read

this means that the XSLT processor will never know that a space in an attribute value,
used to be a carriage return,
so whatever you do in your XSLT program, you can't bring the carriage return back

that is why there is a
<xsl:preserve-space elements="..." />
and not
<xsl:preserve-space attributes="..." />
because that makes no sense

the spaces that remain are automatically preserved

So, if you really want to preserve the carriage-returns
you will have to put them in an element instead of an attribute

hope this now explains it well enough

I hope you have access to the source XML file
and you can change it at the source
If you need to convert the attributes to elements
you will have to do that using text processing techniques,
because if you use XML techniques (whatever, DOM, SAX, XSLT,...)
there will be a parser first, and the parser will normalize the attribute value
... back to square root one

I can write you a small Ruby program that does the transform for you,
if you want to





is there any resource u recommend for converting the attributes to elements?


how would i go about implementing this ruby program?

i'm viewing the xml in xmlspy incase thats of any use.
Gertone (Geert Bormans)Information Architect
Top Expert 2006

I will show you over the weekend, if that is OK for you
Gertone (Geert Bormans)Information Architect
Top Expert 2006


switching machines took a bit longer than expected

I have a little Ruby program here that takes the attribute
and puts it in an element with the same name, immedeatly after the opening tag
You can now preserve the spaces in XSLT

what you should do
- download ruby 1.8 and install it (
- save the below snippet as a file attr2elem.rb
- run this command-line: ruby attr2elem.rb source.xml > result.xml

note that the source and result xml files can have other names

Here is what you can do then
- get the original XML, transform with the ruby program and then transform in a second step using XSLT with preserve spaces

The Ruby program:
class ReplaceList
      def initialize
            @for_element = ""
      def evaluate_tag_content(str)
            re = /((Client_Comment)=(["'])(.*?)\3)/m
            if md = re.match(str)
                  @for_element = "<" + md[2] + ">" + md[4] + "</" + md[2] + ">"
              "#{ unless md.pre_match.nil?; md.pre_match; else ''; end; }" +
                  "#{ unless md.post_match.nil?; md.post_match; else ''; end; }"
                  @for_element = ""
      def extract_tags(str)
            re = /<([^>]+?)>/
            if md = re.match(str)
              "#{ unless md.pre_match.nil?; md.pre_match; else ''; end; }" +
                  '<' + evaluate_tag_content(md[1]) + '>' + @for_element +
                  "#{ unless md.post_match.nil?; extract_tags(md.post_match); else ''; end; }"

lines =
while line = gets
            lines << line

tagger =
puts tagger.extract_tags(lines.join)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial