tags:

views:

712

answers:

2

Hey everyone

Im trying to use XSL and Xpath functions to remove all the white space from a XML attribute called name and make it lower case. At the moment i have something like

 <xsl:variable name="linkName">
 <xsl:value-of select="normalize-space(name)"/>
 </xsl:variable>

This removes the white space at the beginning and end but not the middle. Any suggestions?

What is the best practice for handling and altering XML data as it seems that you can use

<xsl:value-of select="x"/>

placed directly in the HTML

or

<xsl:attribute name="y">
<xsl:value-of select="x"/>

or use a

<xsl:variable name="x">

I'm not really sure of the differences or when each should be used. Any help is much appreciated.

Ally

+1  A: 

This removes the white space at the beginning and end but not the middle. Any suggestions?

You could use the translate(' &#13;&#10;', '') to strip space, newline and carriage return characters. If you're using the .NET classes or MSXSL to do your transform then it's a little difficult to turn characters to lower case. One hack I've used is to use transform to turn upper case letters to their lower case counterparts; another is to write a .NET extension object to provide a lower-case function. The lower-case function is built into XPath/XSL 2.0.

In the second part of your question, they do different things:

  • <xsl:value-of ... places a value directly in the HTML
  • <xsl:attribute ... creates an attribute on the current HTML element and assigns it a value
  • <xsl:variable ... declares an XSL variable without affecting the HTML. You can write this variable into the HTML by using <xsl:value-of select="$x"/>.
Tim Robinson
+2  A: 

As Tim Robinson points out, translate will do the trick. (I wouldn't call it a "hack," but then I've long been at the identifying-with-my-torturers stage of my relationship with XSLT.) Your code will be a lot more readable if you use something like this:

<xsl:variable name="uc" value="ABCDEFGHIJKLMNOPQRSTUVWXYZ"/>
<xsl:variable name="lc" value="abcdefghijklknopqrstuvwxyz"/>
<xsl:variable name="ws" value=" &#13;&#10;&#09"/>

...which is part of the globals.xslt file that I include at the top of most transforms I write. Then this:

<xsl:value-of select="translate(x, concat($uc, $ws), $lc)"/>

translates each upper-case letter into its lower-case equivalent, and each whitespace character into nothing.

Usually the reason you use xsl:variable is to make code more readable (as in the above example), or to store intermediate results that can't otherwise be effectively calculated. A fourth way of getting data into the output is one you didn't mention, and that's pretty darned useful: the attribute value template. All of these do the same thing:

<link>
   <xsl:attribute name="name">
      <xsl:value-of select="translate(name, concat($uc, $ws), $lc)"/>
   </xsl:attribute>
</link>

<link>
    <xsl:attribute name="name" value="translate(name, concat($uc, $ws), $lc)"/>
</link>

<xsl:variable name="linkName" value="translate(name, concat($uc, $ws), $lc)"/>
<link name="{$linkName}"/>

In this particular case, it's arguable which of the last two is simpler and clearer. Most of the time, though, it's not: separating the calculation of values from how they get inserted into the output makes both easier to understand, as does using an AVT instead of more verbose XSLT constructs that do the same thing.

Robert Rossney