A RELAX NG Grammar for XSLT 2.0 and the marvelous simplicity of externalRef.
As XSLT 2.0 matures, and with Michael Kay’s excellent processor (from Saxonica) available to start putting it through it’s paces in practice, I’ve been writing more and more XSLT 2.0 stylesheets.
I’ve been doing it in emacs, of course,
nxml mode. That ships with
an XSLT 1.0 grammar and I’ve just
been ignoring the apparent “errors” in 2.0 stylesheets.
Until yesterday, that is. Yesterday, I got fed up with my editor’s
failure to detect
as attributes in the wrong place
and I went ahead and constructed an
XSLT 2.0 grammar.
James got his grammar for 1.0 by running some XSLT over the grammar description in the spec. Not having that stylesheet handy, I just did it by hand. If you find any errors, let me know and I’ll fix them.
Having a grammar for 2.0 is nice (a usable grammar, I mean, the W3C XML Schema version in the spec doesn’t do me any good), but it raises a new problem: how do I get emacs to use the 2.0 grammar for 2.0 stylesheets and the 1.0 grammar for 1.0 stylesheets?
The short answer is: there isn’t any way (it could be done, but not with
any of the techniques provided by an unmodified
nxml mode). What I really needed was
a stylesheet for either version of XSLT.
As I pondered how this might be done, how I might reconstruct the various
patterns to account for whether or not they were descended from a
<xsl:stylesheet> element with a
attribute of “1.0” or “2.0”, I remembered “
externalRef”, a RELAX NG
feature I hadn’t really needed before.
You want to see how easy it is to build a RELAX NG grammar that will validate either XSLT 1.0 or XSLT 2.0 stylesheets? It’s just this simple:
1xslt10 = external "xslt10.rnc" 2xslt20 = external "xslt20.rnc" 3start = xslt10 | xslt20
How sweet is that? For your convenience, I’ve put that schema and a copy of James’ original online too.
I should point out that this doesn’t automatically handle mixtures of XSLT 1.0 and XSLT 2.0 elements in the same stylesheet. But it does validate entire stylesheets one way or the other.