This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
Re: msxml and xml:space
- From: Jeni Tennison <jeni at jenitennison dot com>
- To: Simon Dell <simondl at epic dot co dot uk>
- Cc: xsl-list at lists dot mulberrytech dot com
- Date: Fri, 16 Aug 2002 17:56:48 +0100
- Subject: Re: [xsl] msxml and xml:space
- Organization: Jeni Tennison Consulting Ltd
- References: <5.1.0.14.0.20020816170515.02bb0570@post.epic.co.uk>
- Reply-to: xsl-list at lists dot mulberrytech dot com
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>
 </xsl:text>
<xsl:apply-templates select="./node()"/>
<xsl:text>
 </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