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:
- 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.
- 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.