[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: msxml and xml:space

Subject: Re: msxml and xml:space
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Fri, 16 Aug 2002 17:56:48 +0100
xsl for each space
Hi Simon,

> I wonder if anyone can offer a suggestion to this little problem.
> I have an XSLT template which includes the following:
>
>                          <xsl:for-each select="tabTitle">
>                                  <div class="tabTitle">
>                                  <xsl:attribute 
> name="id">title<xsl:value-of select="position()"/>DIV</xsl:attribute>
>                                  <xsl:attribute 
> name="style">position:absolute; left:<xsl:value-of
> select="40+((position()-1)*151)"/>px; top:57px; width:120px; height:46px; 
> z-index:3</xsl:attribute>
>                                          <xsl:apply-templates 
> select="./node()"/>
>                                  </div>
>                          </xsl:for-each>
>
> (sorry about any wrapping)
>
> I would expect this to generate a number of lines similar to this
> one: <div class="tabTitle" id="title1DIV" style="position:absolute;
> left:40px; top:57px; width:120px; height:46px; z-index:3">Hospital
> access</div>
>
> ...and this seems to be the case most of the time.
>
> However, when my <xsl:template> tag includes the
> xml:space="preserve" attribute, neither of the <xsl:attribute/> tags
> from the main body of the template are acted apon and the DIVs come
> out w/out the attributes.
>
> I'd like to be able to preserve the document spacing, so does anyone
> have any ideas?

Coo, interesting twist. When you put xml:space="preserve" on your
xsl:template element, you're saying "all the whitespace in this
template is significant". It's just as if you wrapped the whitespace
in xsl:text elements:

  <xsl:for-each select="tabTitle"><xsl:text>
    </xsl:text><div class="tabTitle"><xsl:text>
      </xsl:text><xsl:attribute name="id">title<xsl:value-of
select="position()"/>DIV</xsl:attribute><xsl:text>
      </xsl:text><xsl:attribute name="style">position:absolute; left:<xsl:value-of
select="40+((position()-1)*151)"/>px; top:57px; width:120px; height:46px;
z-index:3</xsl:attribute><xsl:text>
      </xsl:text><xsl:apply-templates select="./node()"/><xsl:text>
    </xsl:text></div><xsl:text>
  </xsl:text></xsl:for-each>

(Note that this is preserving the whitespace from the *stylesheet*
rather than the whitespace from the *source document*; I'm not sure
whether that's what you want to do [it's a pretty rare thing to want
to do!]).

The trouble is that you can't add content to an element before you add
attributes to that element -- if you try to then (as you've found) the
attributes are ignored. Whitespace counts as content.

A good solution, given that your attributes are pretty simple, is to
use attribute value templates rather than xsl:attribute. Try:

  <xsl:for-each select="tabTitle">
    <div class="tabTitle"
         id="title{position()}DIV"
         style="position:absolute; left:{40+((position()-1)*151)}px;
                top:57px; width:120px; height:46px; z-index:3">
      <xsl:apply-templates />
    </div>
  </xsl:for-each>

See how the xsl:value-ofs in your xsl:attributes get translated into
{...} within the attribute value?
  
[Note that I've also removed the select attribute from
xsl:apply-templates -- it applies templates to the child nodes of the
context node by default, so there's no need to specify it explicitly.]

Another (more general) solution would be to stop preserving space
within the particular div element and to use xsl:text to add the space
that you want explicitly. Something like:

  <xsl:for-each select="tabTitle">
    <div class="tabTitle" xml:space="default">
      <xsl:attribute name="id">title<xsl:value-of
select="position()"/>DIV</xsl:attribute>
      <xsl:attribute name="style">position:absolute; left:<xsl:value-of
select="40+((position()-1)*151)"/>px; top:57px; width:120px; height:46px;
z-index:3</xsl:attribute>
      <xsl:text>&#xA;    </xsl:text>
      <xsl:apply-templates select="./node()"/>
      <xsl:text>&#xA;  </xsl:text>
    </div>
  </xsl:for-each>

Or you could look into using:

  <xsl:output indent="yes" />

to make your output nicely indented (*how* nicely depends on the
processor) automatically rather than adding whitespace manually.
  
Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.