Reputation: 125
I'm trying to add an attribute to the 'xsl:element name="div"' element from another template, the 'xsl:template match="KTheme"' template, but I get a XSLT error with no error information about what failed or why it failed. Is there a way of doing this?
Basically, when the 'xsl:apply-templates/' line is executed from the 'xsl:template name="DisplayFrame"' template, it matches against the 'KTheme' elements and should add the "style" attribute to the "div" element:
<xsl:template match="Frame">
<xsl:call-template name="DisplayFrame">
<xsl:with-param name="FrameId" select="'frameHeader'" />
</xsl:call-template>
</xsl:template>
<xsl:template name="DisplayFrame">
<xsl:param name="FrameId" />
<xsl:element name="div">
<xsl:attribute name="id">
<xsl:value-of select="$FrameId" />
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
The template below is where the "style" attribute should be added to the "div" element. This template is the one giving me an error, because once I remove the 'xsl:attribute' element the XSLT compiles sucessfully.
<xsl:template match="KTheme">
<xsl:attribute name="style">
<xsl:value-of select="." />
</xsl:attribute>
</xsl:template>
An example XML file:
<Document>
<Frame>
<KTheme>background-color: red;</KTheme>
</Frame>
</Document>
In reality, the 'KTheme' element is dynamically created, so it must be done as my theory suggests, by adding an attribute from another template, but apparently it is incorrect. Can this be done? Thank you for your time.
Upvotes: 2
Views: 2188
Reputation: 101758
What's happening here is that there are whitespace text nodes before and after KTheme
, and the one before it is being added to the output before the attribute. It is an error to try to add an attribute to a parent element after a non-attribute node has been added to it.
To play it safer, I recommend directly targeting the KTheme
element, and then processing anything else. This should fix your problem:
<xsl:template name="DisplayFrame">
<xsl:param name="FrameId" />
<div id="{$FrameId}">
<xsl:apply-templates select="KTheme" />
<xsl:apply-templates select="node()[not(self::KTheme)]" />
</div>
</xsl:template>
I also made it a little cleaner with the use of an attribute value template for the id attribute, but that's not a necessity.
As a side note, adding <xsl:strip-space elements="*"/>
to the top of the XSLT to strip out the whitespace text nodes would have also prevented this error, but I still think it's wiser to actively target anything that could produce attributes before you handling anything else. Accidentally adding an attribute at the wrong time can cause your whole XSLT to fail.
Upvotes: 2
Reputation: 12729
... or with AVT for @style
...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()" name="ident">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Frame">
<div id="frameHeader" style="{KTheme}">
<xsl:apply-templates select="node()[not(self::KTheme)]" />
</div>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1