abbf53312a7e918a7bf00a26193bdf9be6e4fcec
[homepage.git] / blog / posts / 2008 / 02 / XQuery_and_XSLT_2.0_with_Debian.mdwn
1 # XQuery 1.0 and XSLT 2.0: news and how to use them in Debian
2
3 <small>(long post about the second generation of the XSL family and how to use
4 the related languages in Debian)</small>
5
6 * <a href="#xsl2">XPath 2.0, XQuery, et al.</a>
7 * <a href="#debian">the above stuff .. in Debian</a>
8 * <a href="#links">links</a>
9
10 ----
11
12 <a name="xsl2" />
13 ## The 2nd generation of the XSL family
14
15 At the beginning of 2007, [W3C](http://www.w3.org) released a
16 [family](http://www.w3.org/Style/XSL/) of interrelated specification: [XPath
17 2.0](http://www.w3.org/TR/xpath20), [XSLT 2.0](http://www.w3.org/TR/xslt20),
18 [XQuery (1.0)](http://www.w3.org/TR/xquery/). The 3 specifications are based on
19 the very same underlying [data model](http://www.w3.org/TR/query-datamodel)
20 which (finally!) supports **typed values** and exploits them to some extent, for
21 example permitting some form of **static type checking** in XPath and XQuery.
22 Types usually come from [XML Schema](http://www.w3.org/XML/Schema), with both
23 built-in and user-defined types supported.
24
25 A brief overview of the 3 specifications and what they change in the state of
26 the art follows.
27
28 <a name="xpath20" />
29 ### XPath 2.0
30
31 *XPath 2.0* basically consists in [XPath 1.0](http://www.w3.org/TR/xpath) + 3
32 new macro features. The first one is a revamp of those language features which
33 are dealing with types, in order to better integrate them with the new typed
34 data model. XPath now has operators to check whether a value belongs to a given
35 type (so yes, type information are kept at run time), and to cast them from one
36 type to another. The basic new type constructor is now the *sequence*, which
37 replaces the old node-set solving many annoying issues, such as the
38 impossibility of having a node ordering other than *document order*.
39
40 The second feature is the improvement of *standard library* of functions which
41 was ridiculously small in XPath 1.0; it is much better
42 [now](http://www.w3.org/TR/xpath-functions/). Additionally, 2nd generation
43 languages ([XSLT 2.0](#xslt20) and [XQuery](#xquery)) now support the ability to
44 define functions which will then be visible to inner (XPath) expressions,
45 pushing yet forward the possibilities of plain old XPath. Functions can now also
46 declare types in their signatures (for their arguments and return value) and
47 untyped arguments will be automatically casted to them upon invocation. Hence,
48 even if you are not using an implementation which assigns types to your XML
49 trees, once you "enter" the typed world calling a typed function (almost all
50 standard library functions are decently typed) you will be able to stay there
51 avoiding annoying casts everywhere.
52
53 Finally XPath 2.0 has turned into a powerful *purely functional language* and is
54 now powered by constructs like conditionals, for-each loops,
55 existential/universal quantifiers, and existentially-quantified comparison
56 operators for sequences. Here is a complex expression to hwet your appetite (or
57 scare you away ...), comments come as <kbd> (: smiley faces \:) </kbd>
58
59     for $book in /bookshelf//books
60     return
61       if ((every $author in $book/authors/author
62            satisfies $author/nativeLang eq "it_IT")
63           and $book/lang eq "it_IT")
64       then $book
65       else ()
66
67     (: think about the trouble of writing this in XSLT/XPath 1.0 ... \:)
68
69 <a name="xslt20" />
70 ### XSLT 2.0
71
72 XSLT 2.0 is what I would call a "bug fix release" of XSLT 1.0 + the routinary
73 reworking of the language to deal with typed values, which is not sensibly
74 different than what has been done for XPath 2.0. The fixed "bugs" are several,
75 starting from the annoying issue of *result tree fragments*. They are basically
76 tree snippets that in XSLT 1.0 you were able to generate for future use.
77 Unfortunately they were not thaaat reusable, given that you were not even able
78 to navigate them with XPath operators! Now the specification is much more clear
79 and distinguishes *final result trees* from ordinary variables, which can now
80 contain sequences of (navigable) tree nodes.
81
82 Another important "bug" fixed is the new ability to *output multiple documents*
83 with a single XSLT stylesheet: it marks the end of stupid extra post processing
84 to be added in pipeline to a XSLT processor.
85
86 Other minor "bugs" fixed are a limited amount of *backtracking* capabilities
87 among imported templates, regular expression support directly in the language,
88 and powerful *grouping* constructs on the lines of SQL's <kbd>GROUP BY</kbd>
89 (but much more powerful). Here is a template snippet exploiting the latter
90 feature:
91
92     <xsl:for-each-group select="*" group-starting-with="h1">
93       <div>
94         <xsl:apply-templates select="current-group()" />
95       </div>
96     <xsl:for-each-group>
97
98 <a name="xquery" />
99 ### XQuery
100
101 XQuery is the end of the chains imposed by XML-based syntaxes. Why the heck one
102 has to use an XML syntax (as in the above snippet) only because she is
103 manipulating XML tress is one of the mysteries of XML technologies which have
104 always been floating around in my head.
105
106 XQuery is the (supposedly) SQL equivalent for databases of XML documents, but is
107 actually much more than that. I depict it in my head as *the* XML manipulation
108 language with a syntax I can finally stand. Technically it is XPath
109 2.0 (say 80% of the whole language) + some extra ingredients (say 20%); so
110 remember that every XPath 2.0 expression is also a XQuery expression.
111
112 The main extra ingredient is the so called *FLWOR expression* (to be read:
113 "flower expression", which in addition to the "smiley faces" used for comments
114 gives a "back to 1968"-flavour to the language .... erm FLWOR/flower/flavour, no
115 pun intended). A FLWOR expression is very similar to SQL's SELECT-FROM-WHERE: it
116 lets you generate a *tuple stream* by iterating on sequences (**F**: *for*
117 clauses), binding expression values to names (**L**: *let* clauses), filter out
118 tuples which do not satisfy a required condition (**W**: *where* clause), order
119 the survived tuples (**O**: *order by* clause), and finally return a sequence
120 built using the residual tuple stream (**R**: *return* clause).
121
122 The other interesting extra ingredient is the ability to build the *XML
123 snippets* you want to manipulate. Within XQuery you do that using plain XML
124 syntax (the only place where a sane-minded programmer actually wants to see it!)
125 which also supports a classical *interpolation* mechanism to embed expressions
126 which will be evaluated inside XML snippets, and also the other way around. A
127 canonical XQuery example is:
128
129     for $t in doc("books.xml")//title,
130         $e in doc("reviews.xml")//entry
131     where $t = $e/title
132     return <review>{ $t, $e/remarks }</review>
133
134     (: braces denote the escaping context where XQuery expressions will
135        be evaluated inside snippets; plain XML syntax is used for the
136        other way around \:)
137
138 But remember: XQuery for XML is much more than SQL for RDBMS, thanks to the
139 implicit templating mechanism implemented by interpolation, and thanks to
140 several language features fostering modularity (user-defined functions, library
141 modules, XPath 2.0 standard library, ...) you can basically do with it any kind
142 of XML manipulation you can imagine.
143
144 <q>I don't think I will ever write myself any other single line of XML output in
145 DOM or XSLT ...</q>
146
147 ----
148
149 <a name="debian" />
150 ## Cool, how can I use it in Debian?
151
152 <q>... if only this stuff were decently supported in the open source world.</q>
153
154 Last time I checked, the author of most parts of the GNOME toolchain for dealing
155 with XML (libxml2, libxslt, ...) was not intentioned to implement XSLT 2.0, not
156 even mentioning XQuery. This comes as no surprise, the whole GNOME XML toolkit
157 is written in C, and XSLT 2.0 / XQuery have reached a level of complexity and
158 formal specification which usually entails a higher level approach. So on the
159 GNOME side we are stuck.
160
161 The other open source implementations of XSLT 2.0 / XQuery I'm aware of are
162 [Saxon](http://saxon.sourceforge.net) and [Galax](http://www.galaxquery.org).
163
164 Saxon is an XSLT 2.0 and XQuery implementation written in Java, which is
165 unfortunate per se. Additionally, it is also unfortunate that it is only
166 *partially open source*. Indeed, Saxon is split into SaxonB (for "basic") which
167 is open source under the Mozilla Public License and SaxonSA which is commercial.
168 While SaxonSA is a fully conformant, XML Schema-aware processor, with support
169 for static typing, SaxonB is a basic-conformant processor with no type-aware
170 features and actually much less optimized than SaxonSA. This is annoying.  (Much
171 more annoying is the fact that SaxonSA's author is the only editor of the XSLT
172 2.0 specification and that instead of his mail address the specification
173 includes an URL pointing to the website selling SaxonSA ...)
174
175 Galax is an open source (IBM CPL / Lucent license) OCaml implementation of
176 XQuery which is not fully conformant to the specification (though it gets quite
177 close) which is type-aware and implements static typing.
178
179 The only XQuery / XSLT 2.0 implementation available *in Debian* at the time of
180 writing is SaxonB. The binary package is [[debpkg libsaxonb-java]], kudos to
181 Michael Koch and the Debian Java Maintainers for having packaged it (and to have
182 stood some annoying pings of mine :-) [[debbug 408842]]).
183
184 To execute XQuery code you just have to <kbd>aptitude install
185 libsaxonb-java</kbd>, prepare a <kbd>query.xq</kbd> file containing your query,
186 and then execute something like:
187
188     CLASSPATH=/usr/share/java/saxonb.jar \
189     java net.sf.saxon.Query query.xq
190
191 note that the information in README.Debian are still referring to old Saxon
192 versions, see [[debbug 465894]] which proposes a more up to date README.Debian.
193
194 Similarly, to perform a XSLT 2.0 transformation you have to do something like:
195
196     CLASSPATH=/usr/share/java/saxonb.jar \
197     java net.sf.saxon.Transform -ext:off -s:input.xml -xsl:style.xsl -o:output.xml
198
199 Do not remove the -ext:off flag when processing *untrusted stylesheets*!, see
200 [[debbug 465885]] for the reason.
201
202 I've written some handier (1-liner) shell script helpers which remove the need
203 of invoking java manually. They are attached to [[debbug 465894]] and I've
204 proposed their addition to the saxonb package. Using them the above invocations
205 become:
206
207     saxonb-xquery query.xq
208
209     saxonb-xslt -ext:off -s:input.xml -xsl:style.xsl -o:output.xml
210
211 Galax in Debian ... well, since long time I've been planning to package it (the
212 ITP has been filed some months ago: [[debbug 447984]]) and the authors sent me a
213 newer version than what is available online to gather feedback before the long
214 overdue final release. Unfortunately I've been lagging behind in finishing the
215 packaging (which is tricky due to the need of binding libraries to several
216 different languages: OCaml is native, but there is also Java for example).
217 Hopefully this post will give me some renewed motivation for finishing the work
218 ...
219
220 ----
221
222 <a name="links" />
223 ## References
224
225 * Debian package [[debpkg w3-recs]], ships the whole list of W3C Recommendations
226 for offline consultation; it includes all the specifications we have discussed
227 in this post
228 * [Saxon](http://saxon.sourceforge.net): home page of Saxon, a XSLT 2.0 /
229 XQuery processor written in Java
230 * [Galax](http://www.galaxquery.org): home page of Galax, a XQuery processor
231 written in OCaml
232 * Debian package [[debpkg libsaxonb-java]], ships SaxonB as a Debian package
233
234 ----
235
236 ## Acknowledgements
237
238 Thanks to [godog](http://esaurito.net/blog) for his helpful comments.
239
240 ----
241
242 **Update**: the helpers I've proposed have been accepted into the official
243 package, I've also made available their manpages. Also the pending changes to
244 README.Debian has been accepted. Kudos again to Michael Koch for his quick
245 feedback on my patches!
246
247 [[tag lang/english planet/debian xml xslt xquery debian]]