February 6, 2007

Generating XML entity references (&foo;) with XSLT: XSLT 2.0 to the rescue

Here is a problem: XSLT 1.0 sucks on generating XML character or entity references. I mean getting &foo; out of XSLT 1.0 is hard. The only ugly solution is disable-output-escaping hack, but it's a) optional, b)doesn't work in all scenarios (only when XSLT engine controls output serialization into bytes and c) works only on text nodes. Latter is real showstopper - you can't generate character or entity reference in attribute using XSLT 1.0. But now that we have XSLT 2.0, which is oh so better. What's XSLT 2.0 solution for the problem?


In XSLT 2.0 disable-output-escaping is deprecated. New facility for the problem is called Character Maps. Character maps are simpler, better and don't mess with data model. Formal definition:

A character map allows a specific character appearing in a text or attribute node in the final result tree to be substituted by a specified string of characters during serialization. The effect of character maps is defined in [XSLT and XQuery Serialization].

This is basically declarative replace for XSLT output.

Let's say you want to generate this XUL fragment (real world question):

<menuitem label="&context.add.building;"/>

XSLT 2.0 solution would be to define a character map, which maps ampersand character to ugh... ampersand character :) For this to make sense you should realize that mapping a character effectively disables its XML or HTML escaping. It's like you say "I want this character to be outputted as this string and don't mess with it you, the engine". That's powerful enough even to disable escaping of reserved characters such as & and <.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output use-character-maps="xul" />
    <xsl:character-map name="xul">
        <xsl:output-character character="&amp;" string='&amp;'/>
    <xsl:template match="contextMenu">
	<menuitem label="&amp;context.add.{name()}"/>

Awesome. I can't wait, I want this in XSLT 1.0 too. I think I'm going to implement character maps for nxslt.exe tool. The only problem is how to provide mapping info. I'll post about it next time.

[Tested with Saxon 8.8B for .NET].


Google somehow seems to be inaccessible (down?) from my place for at least 15 minutes now and I already feel uncomfortable  if not desperate. I want my mail, news and search back! Seriously, WTF? How come can I be so dependent on google? Ok, great, who else does search on the Web?



Everybody who speaks English can communicate with anybody else who also happens to speak English. You can talk, you can mail, you can read books written in English by others.

Sure you can invent your own language, no big deal. You can even make somebody learn it and then talk to her.

But most prefer easy way and speak XML, I mean English.

[Well, technically speaking majority on this planet prefer Chinese anyway].