Amusingly MOSS

...It's funny how difficult some stuff is when it really shouldn't be

  Home  |   Contact  |   Syndication    |   Login
  29 Posts | 0 Stories | 34 Comments | 0 Trackbacks

News

Twitter












Tag Cloud


Archives

Post Categories

And I don't mean the Diet Coke of Evil (only one calorie, not evil enough). I spent most of today finding out the most stupid of things.

All I wanted to do was to create a blasted <img /> tag that had its source attribute set dynamically by XSLT.  Seems pretty run-of-the-mill, eh?  Here's the XSLT (I've even replaced the xpath with hard-wired text to simplify the scenario):

<xsl:stylesheet version="1.0" extension-element-prefixes="msxsl" exclude-result-prefixes="msxsl js dl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:js="urn:custom-javascript" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:dl="urn:datalist">
  <xsl:output method="xml" version="1.0" omit-xml-declaration="yes" indent="yes" encoding="utf-8"/>
  <xsl:template match="/" xml:space="preserve">
  <div class="sponsorLogo">
    <xsl:element name="img">
     <xsl:attribute name="src">test.gif</xsl:attribute>
   </xsl:element>
  </div>
 </xsl:template>
</xsl:stylesheet>

I fired up my trusty, dusty C# transform method that I've used for quite a while, passed in the XML I want to transform with the above XSLT, and BOOM! I get this .NET runtime error:

Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added.

What on earth?!  I've done this sort of thing many, many times, so why now?  Well, here's the reason:

<xsl:template match="/" xml:space="preserve">

It turns out that this attribute tells the XSLT parser to treat the white space I was using to indent/format my xslt as actual text, which makes the above error make a lot more sense.  I stripped out the xml:space="preserve" attribute, and poof, everything worked perfectly.

So, there are really two lessons to be learned here:

  1. xml:space="preserve" treats ANY white space (to include line breaks) as actual text, so don't use it if you plan on making your XSLT readable by any human being.
  2. Don't cut-and-paste an XSLT document from some other system without first being SURE you know what your headers are doing.

What a disaster.  Now, it's time to go home.  Have a good weekend, everyone.

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati
posted on Friday, May 15, 2009 5:43 PM

Feedback

# re: XSLT is Pure Evil 5/17/2009 9:50 AM Alain
I always believed that XSLT was an April Fools joke, but apparently some people believed it was meant to be used.

# re: XSLT is Pure Evil 5/17/2009 2:59 PM Phillip
Why not try? <img src="{images/src}" />

# re: XSLT is Pure Evil 5/17/2009 4:02 PM Kfir
does finding some xlst caveat really call for the sensationalist title?!

# re: XSLT is Pure Evil 5/18/2009 7:53 AM David
To me it looks as an expected error if you look at it from a streaming perspective, otherwise the xslt transformer would need to buffer the output, which is insane from performance perspective.

# re: XSLT is Pure Evil 5/18/2009 11:53 AM Adam McKee
Perhaps "XSLT is Pure Evil" is a sensationalist title from the standpoint of the subject matter being very small in the grand scheme of the awesome things that you can accomplish through the use of XSLT.

However, I feel that the amount of hair I pull out to accomplish those awesome things through XSLT is rarely justified in the long run (especially considering that I don't have that much hair left to pull out in the first place).

Perhaps a better title would be, "XSLT makes me bald(er)."

# re: XSLT is Pure Evil 5/18/2009 5:45 PM steve j
@Phillip: the attribute value template is the best way to go and produces the desired markup and formatting. Easy to read too.

@OP: The error message is quite clear about where the problem is. Where's the confusion? ;)
Here are two more ways you could have fixed it:

<xsl:element name='img' xml:space="default">
--or--
<xsl:element name='img'><xsl:attribute ...

(but the second way probably needs the IMG markup on one line for the html parse to be happy with it)



# re: XSLT is Pure Evil 5/18/2009 9:15 PM Adam McKee
@Steve J: Thanks for the tip! I'm mostly on the steep part of the learning XSLT curve at the moment :)

# re: XSLT is Pure Evil 5/19/2009 9:45 AM steve j
No problem.

Just noticed one more thing: output method='xml'.

The output you show looks like it could be: html, xhtml, or xml that strongly resembles html. If you're really after html, then output='html' *might* fix the issue also.

For future issues be sure to seek out Dave Pawson's XSLT FAQ and books by Michael Kay or Jeni Tennison (if you haven't already). HTH.

# XML Literals are pure & Good 5/27/2009 2:21 PM Ben
ok....oop purists might not think so, hence they're not in C#. However - for xml translation / manipulation they are the BOMB! i.e. awesome and well worth investigation. Easy to use, powerful and effective. You just gotta use vb.net.

# re: XSLT is Pure Evil 5/27/2009 2:28 PM Adam McKee
@PM Ben: I'm interested in the VB.Net XSLT components you're talking about - what are they? Where can I find resources on them?

# re: XSLT is Pure Evil 5/28/2009 10:12 AM Ben
@Adam

check out: http://www.dnrtv.com/default.aspx?showNum=119

# re: XSLT is Pure Evil 4/1/2010 6:37 AM Angie
Thank you for sharing!!! You've saved me hours of research time I'm sure! What I can't imagine is, WHAT if ANYTHING is xml:space="preserve" used for??

# re: XSLT is Pure Evil 12/22/2010 9:14 AM Alicia
THANK YOU SO MUCH! I'm new at this stuff, using some existing xslt, and I never would have figured this out on my own. You've saved me HOURS!

# re: XSLT is Pure Evil 6/3/2011 6:57 AM Anamika Patel
Thank you!! Thank you!!Thank you!!

# re: XSLT is Pure Evil 6/20/2011 6:09 PM kapil
Hi , my xslt also give error (Attribute and namespace nodes cannot be added to the parent element after a text, comment, pi, or sub-element node has already been added.) on name="onclick" in xslt given below,

<xsl:for-each select="Features/ProductName">
<xsl:variable name="FileName">
<xsl:value-of select="@fileName"/>
</xsl:variable>
<td align="center">

<xsl:choose>

<xsl:when test="@fileName!=''">
<xsl:element name="a">
<xsl:attribute name="onclick">OpenCarrierOutline('<xsl:value-of select="$ServerName"/>','<xsl:value-of select="$FileName"/>');</xsl:attribute>
<xsl:attribute name="href">#</xsl:attribute>
<xsl:value-of select="."/>
</xsl:element>
</xsl:when>

</td>

</xsl:for-each>


please help

Thanks

kapil Gupta

# re: XSLT is Pure Evil 12/22/2011 12:20 PM ncmiami
This solved my problem - THANK YOU!!!!!!! So freaking ridiculous ...

Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: