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,
with 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 version
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.
Comments:
Hi Norm,
I like the externalRef feature too. I actually would have liked to see an analogous feature in XSLT 2.0 (xsl:call-transform or some such). It would let you use existing stylesheets wholesale, without worry about conflicting modes (especially the default one), variable names, etc. Alas, that wasn't the only fight I lost ;-)
Evan
Yes, that would have been nice. I bet there are a lot of nice things we could have done if we hadn't gotten tangled in the W3C XML Schema type system. And we could have finished in 2002, too! :-)
Thanks for this schema! The "start = xslt10 | xslt20" trick is really cool.
"how do I get emacs to use the 2.0 grammar for 2.0 stylesheets and the 1.0 grammar for 1.0 stylesheets?"
While I don't have entry-help in Vim, I installed your schema so that I can validate XSLT 2.0 documents from within Vim (and from the shell).
I added an entry to my language list, now I get:
$ cat 2_0_simple.xslt
<html xsl:version="2.0" xmlns:xsl="www.w3.org/1999/XSL/Transform" xmlns="www.w3.org/1999/xhtml">
<head> <title>Expense Report Summary</title> </head>
<body> <p>Total Amount: <xsl:value-of select="expense-report/total"/></p> </body> </html>
$ xval 2_0_simple.xslt
[xval] validating 2_0_simple.xslt against
/home/tobi/bulk/xml/schemas/xslt/2_0/rng/xslt20.rnc
[xval] jing:
$ # changed the file
$ xval 2_0_simple.xslt
[...]
[xval] jing:
/home/tobi/data/run/xval/_tests/2_0_simple.xslt:8:68:
error: element "fvalue-of" from namespace "www.w3.org/1999/XSL/Transform" not allowed in this context
$
(it would be great if you could allow backtalkers to enter preformatted code, eg via HTML pre or some Wiki style markup)
"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)."
Does that mean that
groups.yahoo.com/group/emacs-nxml-mode/message/259
can't be used to associate the XSLT 1.0 RNG/RNC with XSLT 1.0 documents and the XSLT 2.0 RNG/RNC with XSLT 2.0 documents?
P.S.
My question was not rhetoric :)
I'd really be interested in an answer.
TIA
I always have a hard time getting to the Yahoo Groups archives (I get infinite redirection), so I can't follow the link you posted, but I expect you're pointing to James' "locating rules" language.
As it stands today, you can't select a schema URI based on an attribute value on the root element (or even on the combination of namespace *and* the name of the root element).
That means there's no way for nxml-mode to tell the difference between XSLT 1.0 and XSLT 2.0. But James and I have exchanged some email on the topic and I think there will be a new version that will be able to cope with the selection.
Thanks for the reply!
Here's what I use:
www.pinkjuice.com/language_list/my_language_list.xml
Works great.
Is there a good debugger for XSLT 2.0?
In my site-lisp\nxml-mode\schema directory I renamed James' original xslt.rnc to xslt10.rnc and installed Norm's xslt.rnc. I visited docbook.xsl and got the message, File mode specification error: (error "Reference not in a grammar at position 2 in c:/Program Files/emacs-21.3/site-lisp/nxml-mode/schema/xslt.rnc") in the echo area. The mode line indicates (nXML Valid). What am I doing wrong?