Wednesday, 2 December 2009

Parsing Conditional Comments With XSLT

This is just a quick heads up if your carrying out XSLT transformations to create HTML pages. The HTML pages I was creating, had to contain the the following conditional comment.

<!--[if IE]>
    <link rel="stylesheet" type="text/css" href="/styles/site_view_ie_hack.css" />
<![endif]-->
When I appended the XSL style sheet template with the statement, it was parsed with the angle brackets escaped, resulting in the conditional comment appearing as text on the actual page rather than as HTML mark-up. To resolve this issue, I had to wrap the statement in a CDATA tag and wrap the CDATA tag in an <xsl:text> tag as so:
<xsl:text disable-output-escaping="yes">
    <![CDATA[
      <!--[if IE]>
          <link rel="stylesheet" type="text/css" href="/styles/site_view_ie_hack.css" />
        <![endif]-->
    ]]>
</xsl:text>

The disable-output-escaping attribute in the <xsl:text> element is the enabling factor in this solution. It instructs the XSL parser not to escape any of the angle brackets in the conditional comment. Placing the conditional comment in a CDATA section ensures the Conditional Comment is parsed in the HTML output otherwise the XSL parser will just treat the conditional comment it as an XSL style sheet comment and won’t render it as output.

I hope this helps.

2 comments:

  1. Martin, using disable-output-escaping is basically circumventing the XML serializer... like using a blender as a hammer. It's usually avoidable, if you know why things are being escaped. See http://www.dpawson.co.uk/xsl/sect2/N2215.html#d3702e223 for more info on that.

    Did you try using xsl:comment rather than xsl:text? That will avoid the escaping of the angle brackets inside the comment on output.

    However you will still need to escape those angle brackets (at least the left ones) in the stylesheet itself, because the stylesheet is in XML, so the left angle brackets are not allowed as part of text (except inside CDATA). To do that you can use &lt; or CDATA as you did. E.g.: (somebody tell me how to format code in blogspot comments?)

    <xsl:comment>[if IE]>
    &lt;link rel="stylesheet" type="text/css" href="/styles/site_view_ie_hack.css" />
    &lt;![endif]</xsl:comment>

    or

    <xsl:comment><![CDATA[[if IE]>
    <link rel="stylesheet" type="text/css" href="/styles/site_view_ie_hack.css" />
    <![endif]]]></xsl:comment>

    Either way, you can avoid disable-output-escaping, and keep markup as markup and text as text.

    FYI, "parsing" refers to the input process, where a string of text is converted into a tree structure. The reverse is "serializing", which is the process of turning a tree structure into a stream of text for output.

    ReplyDelete
  2. Hi Lars.
    Thinking back to when I wrote this post, I was up against a deadline and just needed a solution that worked.
    That said, I can certainly see the benefit of doing it the way you've described and will opt use that method in the future.

    Thanks very much for the feedback.

    ReplyDelete