1. xsl:attribute problem with xml:space
2. xml:space makes xsl:attribute fail


xsl:attribute problem with xml:space

Mike Kay

> <xsl:stylesheet version="1.0" 
> xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> xml:space="preserve"> <xsl:template match="/"> <xsl:element 
> name="foo"><xsl:attribute name="a">test</xsl:attribute>
>             <xsl:attribute 
> name="b">verify</xsl:attribute></xsl:element>
> </xsl:template>
> </xsl:stylesheet>

> Generates the following transform and warning:

> Recoverable error
> at xsl:attribute on line 6 of file:/C:/test.xsl:
>   Cannot write an attribute node when no element start tag is 
> open <?xml version="1.0" encoding="utf-8"?> <foo a="test">
>             </foo>

No, this isn't a bug. Because the whitespace after the <xsl:attribute name="a"> element is significant (by virtue of xml:space), it is copied to the result tree as a text node which will form part of the content of the <foo> element. You can't write another attribute ("b") after you have written a child text node to the containing element. With the default error recovery action, Saxon reports the error and then recovers from it by ignoring the <xsl:attribute> instruction.


xml:space makes xsl:attribute fail

David Carlisle et al

It's normaly a bad idea to preserve space in the stylesheet. If you do....

         <xsl:attribute name="href">

You can't add an attribute after you have added any text to the element body. Normally that newline and space after the <a> would have been stripped and so <xsl:attribute would work but if you preserve that space then it is added as a text node to the output, so you can't add an attribute.

David N Bertoni expands on this :-)

With xml:space="preserve" in the stylesheet, the literal result element now has a text child. Since that text child is generated before the xsl:attribute instruction is instantiated, the processor cannot add the attribute. See: xslt rec

Although the processor is free to halt the transformation at this point, MSXSL is recovering by not adding the attribute.

So, you can move the href attribute into the literal result element:

          <a href="{@start}">
          <xsl:value-of select="title"/>

or reset xml:space to the default:

          <a xml:space="default">
          <xsl:attribute name="href">
                  <xsl:value-of select="@start"/>
          <xsl:value-of select="title"/>

I'm surprised you didn't get a warning from the processor.