tag:blogger.com,1999:blog-330746812024-03-05T09:53:10.831+01:00Nightly thoughtsFlorent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.comBlogger29125tag:blogger.com,1999:blog-33074681.post-9397767751561013042013-02-13T14:59:00.002+01:002013-02-13T15:11:05.361+01:00oXygen, Scala and plugin repository<h2>Introduction</h2>I am looking at Scala for future development, and wondered a bit about its integration abilities for edge cases. Writing a plugin for oXygen looked like a good candidate to investigate this: oXygen has no specific support for Scala, it is written in Java, there is a JAR library containing classes to use for developing the plugin, which has to implement some specific classes and use others, then be bundled as a plugin JAR file, loaded dynamically by oXygen and called from the description in the plugin.xml descriptor. If Scala did not support that scenario, it would probably not be worth having a look at for me.<br />
<br />
So I don't know anything about Scala. I downloaded it, tried to sketch a Hello World kind of plugin for oXygen, and the result was impressively simple! So here are the few steps I've done, if you want to make your own at home.<br />
<h2>Setup</h2>First, download and install Scala. I went to Scala <a href="http://www.scala-lang.org/downloads">download area</a>, downloaded the latest version for Mac OS X, unzip it in <code>/usr/local/scala-2.10.0</code> and added the sub-directory <code>bin/</code> to my <code>$PATH</code>. I assume you also have the oXygen SDK, with the file <code>oxygen.jar</code> to use for plugin development.<br />
<h2>The Scala sources</h2>The following two classes are the implementation of a very simple plugin for oXygen that displays a message when you start oXygen up, and another one when you are about to shut it down. They both must be in a directory called <code>org/fgeorges/test</code> in order to match the package name (exactly like in Java). First the plugin class itself, in <code>org/fgeorges/test/MyPlugin.scala</code>:<br />
<pre class="drkm-code-div">package org.fgeorges.test
import ro.sync.exml.plugin.{Plugin, PluginDescriptor}
class MyPlugin(desc: PluginDescriptor) extends Plugin(desc)
{
// empty plugin
}
</pre>Here is the extension class, in <code>org/fgeorges/test/MyExtension.scala</code>:<br />
<pre class="drkm-code-div">package org.fgeorges.test
import ro.sync.exml.plugin.workspace.WorkspaceAccessPluginExtension
import ro.sync.exml.workspace.api.standalone.StandalonePluginWorkspace
class MyExtension() extends WorkspaceAccessPluginExtension
{
var myws: StandalonePluginWorkspace = null
override def applicationStarted(ws: StandalonePluginWorkspace) {
myws = ws
ws.showInformationMessage("F., yeah!")
}
override def applicationClosing(): Boolean = {
myws.showInformationMessage("We're closing guys...")
true
}
}
</pre><h2>Compiling</h2>In order to compile those, and build the JAR file, go to the top directory (the one containing the sub-directory <code>org/</code>), and use the following command. Note that the <code>-Y</code> is necessary because of some conflicts in the oXygen JAR file when used from Scala. You also might have to adapt the path to the oXygen JAR, of course.<br />
<pre class="drkm-code-div">> scalac \
-Yresolve-term-conflict:error \
-cp .:oxygen.jar \
org/fgeorges/test/*.scala
> jar cf my-plugin.jar org/fgeorges/test/*.class
</pre><h2>Deploying</h2>From now on, you have your plugin as a JAR file, like any other plugin for oXygen. So the next required step is to deploy the plugin like any other plugin. Create a new directory in the oXygen <code>plugins/</code> sub-directory (right under the install directory), and create a plugin descriptor at, say, <code>plugins/my-plugin/plugin.xml</code>:<br />
<pre class="drkm-code-div"><span class="fl-nxml-markup-declaration-delimiter"><!</span><span class="fl-nxml-prolog-keyword">DOCTYPE</span> plugin <span class="fl-nxml-prolog-keyword"><span class="fl-nxml-prolog-keyword">SYSTEM</span></span> <span class="fl-nxml-prolog-literal-delimiter">"</span><span class="fl-nxml-prolog-literal-content">../plugin.dtd</span><span class="fl-nxml-prolog-literal-delimiter">"</span><span class="fl-nxml-markup-declaration-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">plugin</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">MyPlugin</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">description</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Test plugin with Scala...</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">0.0.1</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">vendor</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fgeorges.org</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">class</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">org.fgeorges.test.MyPlugin</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">runtime</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">library</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my-plugin.jar</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">runtime</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">extension</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">WorkspaceAccess</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">class</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">org.fgeorges.test.MyExtension</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">plugin</span><span class="fl-nxml-tag-delimiter">></span>
</pre>All you have to do now to test the plugin is to (re)start oXygen!<br />
<h2>Add-ons repository</h2>A new feature in oXygen 14 (which is not related at all with Scala), is the ability to create an online repository for add-ons (including plugins and frameworks), so a user can point oXygen to it and install add-ons through a graphical interface:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje7w5y_-ufxEoIvBGG6iuqP3NyHsP3FsSL9Ta4KDC4zD6_hAdq4XXqPzv7y01y69ZIHIdfgIN11TUavA8ZwsfwRMfwWVCktbKyGbw4a9qUyoXmX_TCYNB9pGjKMxV9XderJDrWhg/s1600/Screen+shot+2013-02-13+at+14.45.52.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje7w5y_-ufxEoIvBGG6iuqP3NyHsP3FsSL9Ta4KDC4zD6_hAdq4XXqPzv7y01y69ZIHIdfgIN11TUavA8ZwsfwRMfwWVCktbKyGbw4a9qUyoXmX_TCYNB9pGjKMxV9XderJDrWhg/s320/Screen+shot+2013-02-13+at+14.45.52.png" /></a></div>All you have to do in order to create such a repository is to publish a repository descriptor, which links to the JAR files for your add-ons, and give that URL to your users, like you can see on the <a href="http://www.blogger.com/expath.org/oxygen/">EXPath oXygen area</a>. The descriptor looks like the following:<br />
<pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">extensions</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xt</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.oxygenxml.com/ns/extension</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsi</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema-instance</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-prefix">xsi</span><span class="fl-nxml-attribute-colon">:</span><span class="fl-nxml-attribute-local-name">schemaLocation</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
http://www.oxygenxml.com/ns/extension
http://www.oxygenxml.com/ns/extension/extensions.xsd</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">extension</span> <span class="fl-nxml-attribute-local-name">id</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xproject</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">location</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://expath-pkg.googlecode.com/files/xproject-oxygen-plugin-0.5.1.zip</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">version</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">0.5.1</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">version</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">oxy_version</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">14.0+</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">oxy_version</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">type</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">plugin</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">type</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">author</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Florent Georges</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">author</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">name</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">XProject</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">name</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">description</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">XProject, the XML project manager.</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">description</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">license</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Bla bla...</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">license</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">extension</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xt</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">extensions</span><span class="fl-nxml-tag-delimiter">></span>
</pre>Conclusion: Scala is sooo easy to setup to be used to write a plugin for oXygen, and the new oXygen add-on repository is sooo easy to create and to install plugins from!<br />
Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-16179676943949832272011-09-07T23:22:00.006+02:002011-09-07T23:34:07.517+02:00Packaging extension steps for Calabash<p>In my <a
href="http://fgeorges.blogspot.com/2011/09/writing-extension-step-for-calabash-to.html">previous
blog post</a>, I introduced how to develop an extension XProc
step in Java, for the <a
href="http://xmlcalabash.com/">Calabash</a> processor. Even
though writing such an extension is quite easy when you know what
to do, the configuration part for the final user is quite tricky.
That complexity could be a serious argument for a potential user
to give up even before he/she is able to run an example using
your extension step. See the previous blog entry for details,
but basically the user has to configure the classpath for
Calabash with your JAR and all its dependencies, point to your
config file when launching Calabash, and import your library into
the main pipeline (after having decided where to install your
extension step).</p>
<p>At the end of the previous post, I introduced the idea of
having such extension steps, writen in Java for Calabash,
supported out of the box by the repository implementing the
Packaging System. I played a little bit with the idea and came up
with the following design (and implementation). Of course you
still have to provide the same information (the step interface,
its implementation, and the link between its type and the class
implementing it), but the goal is to enable the author to do it
once for all, so the user can simply use the following commands
to install the package and run a pipeline using it:</p>
<pre class="drkm-code-div">
> xrepo install http://example.org/path/to/your-package.xar
> calabash pipeline.xproc
...
</pre>
The only constraint on the user is to use the absolute URI you
defined to import the XProc library you wrote with the step
interface declaration. This absolute URI will be resolved
automatically into the user local repository, and the repository
system will configure Calabash with the Java code automatically.
In order to achieve that goal, you, as an extension step author,
have to provide a package with the following structure:</p>
<pre class="drkm-code-div">
expath-pkg.xml
calabash.xml
your-steps/
your-steps-lib.xpl
your-steps.jar
dependency.jar
</pre>
<p>This structure looks familiar to whoever knows the structure
of a standard package: you have the package descriptor, namely
<code>expath-pkg.xml</code>, containing meta-information about
the package and its content, then within the package directory
you have the components, the content itself of the package. In
addition, you have an additional descriptor, specific to
Calabash, that is <code>calabash.xml</code>. In this case, the
content of the package is an XProc library containing the step
declarations, the JAR file with the compiled Java implementation
of your extension steps, and all its dependencies (the other Java
libraries it uses). Let's see how the two descriptors carry out
all the information needed in order to use the extension steps.
First the standard package descriptor,
<code>expath-pkg.xml</code>:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">package</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://expath.org/ns/pkg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://example.org/lib/your-steps</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">abbrev</span>=<span class="fl-nxml-attribute-value-delimiter">"your</span><span class="fl-nxml-attribute-value">-steps</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">0.1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">spec</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">>Your</span><span class="fl-nxml-text"> XProc steps for Calabash</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dependency</span> <span class="fl-nxml-attribute-local-name">processor</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://xmlcalabash.com/</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">xproc</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">import-uri</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://example.org/your-steps/lib.xpl</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">import-uri</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">>your-steps</span><span class="fl-nxml-text">-lib.xpl</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">xproc</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">package</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Besides the usual informations about the package (its name,
textual description, version number, etc.), we tell that this
package is specific to Calabash (by depending on that
processor). We also declare a public component, a standard XProc
library, by assigning a public, absolute URI to it, and by
linking to its file by name, within the package content. Indeed,
keep in mind that this library declares the step interfaces and
is standard XProc, it remains the same even if there are several
implementations. The library itself is:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">library</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">p</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-attribute-local-name">y</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://example.org/ns/your-steps</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y:some-of-your-steps</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">source</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">option</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"username</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y:another-one</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">library</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Finally, the second descriptor, specific to Calabash and named
<code>calabash.xml</code>, describe the informations about the
Java implementation: the JAR files to add to the classpath, and
the Java class implementing each of the extension step types:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">package</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://xmlcalabash.com/ns/expath-pkg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">jar</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">your-steps.jar</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">jar</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">jar</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">dependency.jar</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">jar</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">type</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">{http://example.org/ns/your-steps}some-of-your-steps</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">type</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">class</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">org.example.yours.SomeStep</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">class</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">type</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">{http://example.org/ns/your-steps}another-one</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">type</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">class</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">org.example.yours.AnotherStep</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">class</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">package</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>The JAR files are referenced by filenames (relative to the
package content dir), the step types are identified by there
QName (using Clark notation, to represent both the namespace URI
and the local name as one single string), and the implementation
class is referenced by it fully qualified name.</p>
<p>The package author has just to respect those conventions and
to provide those two descriptor. He/she can package everything up
by zipping this into one single ZIP file (usually using the
extension *.xar, for <em>XML ARchive</em>). He/she is then able
to publish and distribute the package to users. If the users have
support for the packages, the only piece of documentation to
provide is the public URI of the XProc library, to import it into
their own pipeline.</p>
<p>An interesting point is that this strategy is usable as well
for private extensions. Let's take the set of XSLT 2.0
stylesheets for DocBook for instance. A pipeline, or even a set
of pipelines, might make perfect sense to drive some processings
using this large application. If that processing needs some
extensions to the standard languages, then it is possible to
write extension steps for Calabash, integrate them within the
package with the standard XSLT stylesheets and XProc pipelines,
and to use it internally. If the XProc library declaring the
steps is not publicly exposed in the package descriptor, then
only the other components in the package itself can use it.</p>
<p>In that case, a user using Calabash just installs the package
like any other package, and does not have to, you know, configure
the extensions...</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-61262425269042349282011-09-04T22:46:00.001+02:002013-03-25T14:18:35.683+01:00Writing an extension step for Calabash, to use BaseX<h2>Introduction</h2><p>Writing an extension for Calabash in Java involves three different things: 1/ the Java class itself, which has to implement the interface <code>XProcStep</code>, 2/ binding a step name to the implementation class, and 3/ declaring the step in XProc.</p><h2>Java</h2><p>Let's take, as an example, a step evaluating a query using the standalone BaseX processor. The goal is not to have a fully functional step, nor to have a best-quality-ever step with error reporting and such, but rather to emphasize how to glue all the things together. The step has one input port, named <code>source</code>, and one output port, named <code>result</code>. The step gets the string value of the input port (typically a <code>c:query</code> element) and evaluates it as an XQuery, using BaseX. The result is parsed as an XML document and sent to the output port (it is a parse error if the result of the query is not an XML document or element). Let's start with the Java class implementing the extension step:</p><pre class="drkm-code-div"><span class="fl-drkm-flXcomment">/****************************************************************************/</span>
<span class="fl-drkm-flXcomment">/* File: BasexStandaloneQuery.java */</span>
<span class="fl-drkm-flXcomment">/* Author: F. Georges - H2O Consulting */</span>
<span class="fl-drkm-flXcomment">/* Date: 2011-08-31 */</span>
<span class="fl-drkm-flXcomment">/* Tags: */</span>
<span class="fl-drkm-flXcomment">/* Copyright (c) 2011 Florent Georges. */</span>
<span class="fl-drkm-flXcomment">/* ------------------------------------------------------------------------ */</span>
<span class="fl-keyword">package</span> org.fgeorges.<span class="fl-constant">test</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">com</span>.<span class="fl-constant">xmlcalabash</span>.<span class="fl-constant">core</span>.<span class="fl-type">XProcException</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">com</span>.<span class="fl-constant">xmlcalabash</span>.<span class="fl-constant">core</span>.<span class="fl-type">XProcRuntime</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">com</span>.<span class="fl-constant">xmlcalabash</span>.<span class="fl-constant">io</span>.<span class="fl-type">ReadablePipe</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">com</span>.<span class="fl-constant">xmlcalabash</span>.<span class="fl-constant">io</span>.<span class="fl-type">WritablePipe</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">com</span>.<span class="fl-constant">xmlcalabash</span>.<span class="fl-constant">library</span>.<span class="fl-type">DefaultStep</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">com</span>.<span class="fl-constant">xmlcalabash</span>.<span class="fl-constant">runtime</span>.<span class="fl-type">XAtomicStep</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">io</span>.<span class="fl-type">StringReader</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">Source</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-constant">stream</span>.<span class="fl-type">StreamSource</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">s9api</span>.<span class="fl-type">DocumentBuilder</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">s9api</span>.<span class="fl-type">SaxonApiException</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">s9api</span>.<span class="fl-type">XdmNode</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">basex</span>.<span class="fl-constant">core</span>.<span class="fl-type">BaseXException</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">basex</span>.<span class="fl-constant">core</span>.<span class="fl-type">Context</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">basex</span>.<span class="fl-constant">core</span>.<span class="fl-constant">cmd</span>.<span class="fl-type">XQuery</span>;
<span class="fl-drkm-flXcomment">/**
* Sample extension step to evaluate a query using BaseX.
*
* @author Florent Georges
* @date 2011-08-31
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> BasexStandaloneQuery
<span class="fl-keyword">extends</span> <span class="fl-type">DefaultStep</span>
{
<span class="fl-keyword">public</span> BasexStandaloneQuery(<span class="fl-type">XProcRuntime</span> <span class="fl-variable-name">runtime</span>, <span class="fl-type">XAtomicStep</span> <span class="fl-variable-name">step</span>)
{
<span class="fl-keyword">super</span>(runtime,step);
}
@Override
<span class="fl-keyword">public</span> <span class="fl-type">void</span> setInput(<span class="fl-type">String</span> <span class="fl-variable-name">port</span>, <span class="fl-type">ReadablePipe</span> <span class="fl-variable-name">pipe</span>)
{
mySource = pipe;
}
@Override
<span class="fl-keyword">public</span> <span class="fl-type">void</span> setOutput(<span class="fl-type">String</span> <span class="fl-variable-name">port</span>, <span class="fl-type">WritablePipe</span> <span class="fl-variable-name">pipe</span>)
{
myResult = pipe;
}
@Override
<span class="fl-keyword">public</span> <span class="fl-type">void</span> reset()
{
mySource.resetReader();
myResult.resetWriter();
}
@Override
<span class="fl-keyword">public</span> <span class="fl-type">void</span> run()
<span class="fl-keyword">throws</span> <span class="fl-type">SaxonApiException</span>
{
<span class="fl-keyword">super</span>.run();
<span class="fl-type">XdmNode</span> <span class="fl-variable-name">query_doc</span> = mySource.read();
<span class="fl-type">String</span> <span class="fl-variable-name">query_txt</span> = query_doc.getStringValue();
<span class="fl-type">XQuery</span> <span class="fl-variable-name">query</span> = <span class="fl-keyword">new</span> <span class="fl-type">XQuery</span>(query_txt);
<span class="fl-type">Context</span> <span class="fl-variable-name">ctxt</span> = <span class="fl-keyword">new</span> <span class="fl-type">Context</span>();
<span class="fl-drkm-flXcomment">// TODO: There should be something more efficient than serializing
</span> <span class="fl-drkm-flXcomment">// everything and parsing it again... Plus, if the result is not an XML
</span> <span class="fl-drkm-flXcomment">// document, wrap it into a c:data element. But that</span><span class="fl-warning">'</span><span class="fl-drkm-flXcomment">s beyond the point.
</span> <span class="fl-type">String</span> <span class="fl-variable-name">result</span>;
<span class="fl-keyword">try</span> {
result = query.execute(ctxt);
}
<span class="fl-keyword">catch</span> ( <span class="fl-type">BaseXException</span> <span class="fl-variable-name">ex</span> ) {
<span class="fl-keyword">throw</span> <span class="fl-keyword">new</span> <span class="fl-type">XProcException</span>(<span class="fl-string">"Error executing a query with BaseX"</span>, ex);
}
<span class="fl-type">DocumentBuilder</span> <span class="fl-variable-name">builder</span> = runtime.getProcessor().newDocumentBuilder();
<span class="fl-type">Source</span> <span class="fl-variable-name">src</span> = <span class="fl-keyword">new</span> <span class="fl-type">StreamSource</span>(<span class="fl-keyword">new</span> <span class="fl-type">StringReader</span>(result));
<span class="fl-type">XdmNode</span> <span class="fl-variable-name">doc</span> = builder.build(src);
myResult.write(doc);
}
<span class="fl-keyword">private</span> <span class="fl-type">ReadablePipe</span> <span class="fl-variable-name">mySource</span> = <span class="fl-constant">null</span>;
<span class="fl-keyword">private</span> <span class="fl-type">WritablePipe</span> <span class="fl-variable-name">myResult</span> = <span class="fl-constant">null</span>;
}
</pre><p>An extension step has to implement the Calabash interface <code>XProcStep</code>. Calabash provides a convenient class <code>DefaultStep</code> that implements all the methods with default behaviour, good for most usages. The only thing we have to do is to save the input and output for later use, and to reset them in case the step object is reused. And of course to provide the main processing in <code>run()</code>. The processing itself, in the <code>run()</code> method, we read the value from the source port, get its string value, execute it using the BaseX API, and parse the result as XML to write it to the result port.</p><p>As you can see, there is nothing in the class itself about the interface of the step: its type name, its inputs and outputs, its options, etc. This is done in two different places. First you link the step type to the implementation class, then you declare the step with XProc.</p><h2>Tell Calabash about the class</h2><p>Linking the step type to the implementation class is done in a Calabash config file. So you have to create a new config file, and pass it to Calabash on the command line with the option <code>--config</code> (in abbrev <code>-c</code>). The file itself is very simple, and link the step type (a QName) and the class (a fully qualified Java class name):</p><pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">xproc-config</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://xmlcalabash.com/ns/configuration</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">fg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fgeorges.org/ns/tmp/basex</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">implementation</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg:ad-hoc-query</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">class-name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">org.fgeorges.test.BasexStandaloneQuery</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">xproc-config</span><span class="fl-nxml-tag-delimiter">></span>
</pre><h2>Declare the step</h2><p>Finally, declaring the step in XProc is done using the standard <code>p:declare-step</code>. If it contains no subpipeline (that is, if it contains only <code>p:input</code>, <code>p:output</code> and <code>p:option</code> children), then it is considered as a declaration of a step the implementation of which is somewhere else; if it contains a subpipeline, then this is a step type definition, with the implementation defined in XProc itself. The declaration can be copied and pasted in the main pipeline itself, but as with any other language, the best practice is rather to declare it in an XProc library and to import this library (composed only with step declarations) within the main pipeline using <code>p:import</code>. In our case, we define the step type to have an input port <code>source</code>, an output port <code>result</code> (both primary), and without any option:</p><pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">library</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">p</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">fg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fgeorges.org/ns/tmp/basex</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">pkg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://expath.org/ns/pkg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-prefix">pkg</span><span class="fl-nxml-attribute-colon">:</span><span class="fl-nxml-attribute-local-name">import-uri</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://fgeorges.org/tmp/basex.xpl</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg:ad-hoc-query</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">source</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">library</span><span class="fl-nxml-tag-delimiter">></span>
</pre><h2>Using it</h2><p>Now that we have every pieces, we can write an example main pipeline using this new extension step:</p><pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">p</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">c</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc-step</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">fg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fgeorges.org/ns/tmp/basex</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">pipeline</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">basex-lib.xpl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">fg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">ad-hoc-query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">source</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">inline</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">c</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-entity-ref-delimiter">&</span><span class="fl-nxml-entity-ref-name">lt</span><span class="fl-nxml-entity-ref-delimiter">;</span><span class="fl-nxml-text">res> { 1 + 1 } </span><span class="fl-nxml-entity-ref-delimiter">&</span><span class="fl-nxml-entity-ref-name">lt</span><span class="fl-nxml-entity-ref-delimiter">;</span><span class="fl-nxml-text">/res>
</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">c</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">inline</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">fg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">ad-hoc-query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
</pre><p>To run it, just issue the following command on the command line (where <code>basex-steps.jar</code> is the JAR file you compiled the extension step class into):</p><pre class="drkm-code-div">> java -cp ".../calabash.jar:.../basex-6.7.1.jar:.../basex-steps.jar" \
-c basex-config.xml \
example.xproc
</pre><p>If you use <a
href="http://code.google.com/p/expath-pkg/source/browse/trunk/calabash/bin/calabash">this script</a>, you can then use the following command:</p><pre class="drkm-code-div">> calabash ++add-cp .../basex-6.7.1.jar \
++add-cp .../basex-steps.jar" \
-c basex-config.xml \
example.xproc
</pre><h2>Packaging</h2><p><b>Update</b>: The mechanism described in this section has been implemented, see <a href="http://fgeorges.blogspot.be/2011/09/packaging-extension-steps-for-calabash.html">this blog entry</a>.</p><p>If you want to publicly distribute your extension, you have to provide your users with 1/ the JAR file, 2/ the config file and 3/ the library file. Thus the user needs to correctly configure Java with the JAR file, to correctly configure Calabash with the config file, and to use a suitable URI in the <code>p:import/@href</code> in his/her pipeline. This is a lot of different places where the user can make a mistake.</p><p>The EXPath Packaging open-source implementation for Calabash does not support Java extension steps yet, but it is planned to support them, in order to handle that configuration part automatically. The goal is to have the library author to define an absolute URI for the XProc library (declaring the steps), which the user uses in <code>p:import</code>, regardless of where it is actually installed (it will be resolved automatically). The details (classpath setting, XProc library resolving, and Calabash config) should then be handled by the packaging support. Once the package of the extension step has been installed in the repository, one can then execute the following pipeline (note the import URI has changed):</p><pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">p</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">c</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc-step</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">fg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fgeorges.org/ns/tmp/basex</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">pipeline</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://fgeorges.org/tmp/basex.xpl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">primary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">true</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">fg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">ad-hoc-query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">source</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">inline</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">c</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-entity-ref-delimiter">&</span><span class="fl-nxml-entity-ref-name">lt</span><span class="fl-nxml-entity-ref-delimiter">;</span><span class="fl-nxml-text">res> { 1 + 1 } </span><span class="fl-nxml-entity-ref-delimiter">&</span><span class="fl-nxml-entity-ref-name">lt</span><span class="fl-nxml-entity-ref-delimiter">;</span><span class="fl-nxml-text">/res>
</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">c</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">inline</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">fg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">ad-hoc-query</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
</pre>by invoking simply the following command: <pre class="drkm-code-div">> calabash example.xproc
</pre>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com1tag:blogger.com,1999:blog-33074681.post-63091066518606630202009-11-15T22:22:00.005+01:002010-04-11T04:51:56.466+02:00EXPath Packaging System: the on-disk repository layout<p>While working on the <a
href="http://fgeorges.blogspot.com/2009/11/expath-packaging-system-prototype.html">implementation
for Calabash</a> of the <a
href="http://www.expath.org/modules/pkg/">EXPath Packaging System</a>,
I was rewriting, again, a repository manager, dedicated to Calabash.
Exactly as <a
href="http://fgeorges.blogspot.com/2009/10/expath-packaging-system-prototype.html">I
did for Saxon</a> one month earlier. Why? The repositories provide
the same features. It should be then possible to make Calabash and
Saxon share the same repository, if Saxon just ignore components other
than XSLT and XQuery (for instance XProc pipelines) in that
repository. So one just has to maintain one single repository for
his/her whole computer (or one repository dedicated to a single
project, like a Java EE application.)</p>
<p>Going further, I think the layout of such an on-disk repository
should be part of the <a
href="http://www.expath.org/modules/pkg.html">packaging
specification</a> itself. An implementation does not have to use such a
standard repository, but if it does, it doesn't have to worry about
package installation, repository management software, or even about
the resolving mecanism between a component URI and the actual file
with that component. One repository layout, one set of softwares for
all those tasks.</p>
<p>This introduce a new concept. Each kind of component (XSLT,
XQuery, XML Schema, etc.) has its own <em>URI space</em>. For
instance, when using Saxon for a transform, it will resolve xsl:import
URIs only in the XSLT space, when using Calabash, it will use the
right space for each step. The resolving machinery is based on OASIS
<a
href="http://www.oasis-open.org/committees/documents.php?wg_abbrev=entity">XML
Catalogs</a>. The repository has a top-level catalog for each URI
space.</p>
<p>The global view of the repository is a set of subdirectories, one
per package installed. The package is unzip exactly has it has been
created (with the exact same files and the exact same structure.) One
of those direct subdirectories is special. Its name is
<code>.expath-pkg/</code> and it contains the catalogs and other
administrative files. It can also contain config files dedicated to a
specific processor; for instance the extensions written in Java for
Saxon need some config file to be stored there. There is one
top-level catalog for each URI space in the repository, as well as for
each package there is one catalog for each URI space it contains. The
top level catalogs just point to all existing catalogs at the package
level.</p>
<pre class="drkm-code-div">
repo/
.expath-pkg/
xquery-catalog.xml
xslt-catalog.xml
.saxon/
... [Saxon-specific stuff at the repository level]
lib1/
xquery-catalog.xml
xslt-catalog.xml
saxon/
... [Saxon-specific stuff in lib1]
lib2/
...
lib1/
query.xq
style.xsl
lib2/
...
</pre>
<p>There is a specific project aimed only at managing such a
repository. There is for now only a command line interface, but there
should be a graphical interface in the near future. The same project
provides helpers to other Java-based applications to use repositories.
For instance, the implementations for Saxon and Calabash use this JAR
file to get resolving support for some URI spaces, based on the
Norman's resolver for XML Catalogs. It could then be used in
applications like Kernow and oXygen, or even in eXist. The following
are the steps needed to setup the repository management application,
Saxon and Calabash to have a usable packaging system.</p>
<ul>
<li><b>1/</b> download <a
href="http://www.expath.org/modules/pkg/expath-pkg-repo-0.1.jar">expath-pkg-repo-0.1.jar</a>.
I create a shell script on my system to use it easily by typing
just <code>xrepo</code>, but this is a simple JAR file you can
execute by <code>java -jar pkg-repo.jar</code>. Hereafter I
simply use <code>xrepo</code> to refer to this application.</li>
<li><b>2/</b> set $EXPATH_REPO, for instance to ~/share/expath/repo
or to /usr/local/share/expath/repo or to c:/expath/repo</li>
<li><b>3/</b> initialize the repository with <code>xrepo create
$EXPATH_REPO</code></li>
<li><b>4/</b> put <a
href="http://www.expath.org/modules/pkg/expath-pkg-saxon-0.2.sh">saxon</a>
and <a
href="http://www.expath.org/modules/pkg/expath-pkg-calabash-0.1.sh">calabash
scripts</a> into your $PATH, with the following environment
variables to be able to use them</li>
<li><b>5/</b> set SAXON_CP to the classpath required to execute
Saxon; it must contain the following JARs: saxon9he.jar (or any
other version), <a
href="http://apache.mogo.be/xml/commons/xml-commons-resolver-1.2.tar.gz">resolver.jar</a>,
<a
href="http://www.expath.org/modules/pkg/expath-pkg-repo-0.1.jar">expath-pkg-repo-0.1.jar</a>
and <a
href="http://www.expath.org/modules/pkg/expath-pkg-saxon-0.2.jar">expath-pkg-saxon-0.2.jar</a></li>
<li><b>6/</b> set CALABASH_CP to the classpath required to execute
Calabash; it must contain the following JARs: my modified <a
href="http://www.expath.org/modules/pkg/calabash-expath-r477.jar">version
of Calabash</a>, saxon9he.jar (or any other 9.2 version), <a
href="http://apache.mogo.be/xml/commons/xml-commons-resolver-1.2.tar.gz">resolver.jar</a>,
<a
href="http://www.expath.org/modules/pkg/expath-pkg-repo-0.1.jar">expath-pkg-repo-0.1.jar</a>,
<a
href="http://www.expath.org/modules/pkg/expath-pkg-saxon-0.2.jar">expath-pkg-saxon-0.2.jar</a>
and <a
href="http://www.expath.org/modules/pkg/expath-pkg-calabash-0.1.jar">expath-pkg-calabash-0.1.jar</a></li>
<li><b>4b/</b> instead of the steps 4, 5 and 6 (for example if you
do not have a Unix shell,) you can just create a simple script
with the appropriate classpath and Java command to launch Saxon,
as well as one for Calabash. The only drawback is that the JAR
files for extensions written in Java for Saxon won;t be taken
automatically from the repository</li>
</ul>
<p>We are now going to test the <a
href="http://www.expath.org/modules/http-client/">EXPath HTTP
Client</a>, delivered as a XAR file. First, we create three test
files: an XSLT stylesheet, an XQuery main module and an XProc
pipeline. All those files are simple and use the extension function
http:send-request() to send an HTTP request to a website, get the
result, and extract the HTML title. Save them somewhere as, say,
<code>http-client-test.xsl</code>, <code>http-client-test.xq</code>
and <code>http-client-test.xproc</code>:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">http</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.expath.org/mod/http-client</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">h</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/xhtml</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http h</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.expath.org/mod/http-client.xsl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">request</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">element()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">http</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">request</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.fgeorges.org/</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">method</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">get</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http:send-request($request)
/ h:html/h:head/h:title</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<pre class="drkm-code-div">
<span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> http = <span class="fl-string">"http://www.expath.org/mod/http-client"</span>;
<span class="fl-keyword">declare</span> <span class="fl-keyword">namespace</span> h = <span class="fl-string">"http://www.w3.org/1999/xhtml"</span>;
<span class="fl-function-name">http:send-request</span>(
<http:request href=<span class="fl-string">"http://www.fgeorges.org/"</span> method=<span class="fl-string">"get"</span>/>
)
/ h:html<span class="fl-constant">/h:head/h:title</span>
</pre>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">p</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">c</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc-step</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">source</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">xslt</span> <span class="fl-nxml-attribute-local-name">template-name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">stylesheet</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">document</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http-client-test.xsl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">parameters</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">empty</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">xslt</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>If you try to evaluate those test files before installing the
package, you will get errors from Saxon and Calabash (disclaimer: I
rewrote the outputs of both processors, just make them more easily
readable, but the meaning stays intact):</p>
<pre class="drkm-code-div">
$ saxon -xsl:http-client-test.xsl -it:main
File not found: http://www.expath.org/mod/http-client.xsl
$ saxon --xq http-client-test.xq
Cannot locate module for namespace http://www.expath.org/mod/http-client
$ calabash http-client-test.xproc
File not found: http://www.expath.org/mod/http-client.xsl
</pre>
<p>Now, install the package directly from the Internet (just press
ENTER at both questions from the installer, to keep the default
values,) then try again the test files:</p>
<pre class="drkm-code-div">
$ xrepo install http://www.cxan.org/tmp/expath-http-client-0.1.xar
Install module EXPath HTTP Client? [true]:
Install it to dir [expath-http-client-0.1]:
$ saxon -xsl:http-client-test.xsl -it:main
<title>Florent Georges</title>
$ saxon --xq http-client-test.xq
<title xmlns="http://www.w3.org/1999/xhtml">Florent Georges</title>
$ calabash http-client-test.xproc
<title>Florent Georges</title>
</pre>
<p>While I think the runtime support for the packaging is best handled
in each processor's internals, having a common repository layout (and
actually shared repositories) could help processors to implement it
and especially to have a set of independent applications to manage
repositories and packages.</p>
<p>The next is, finally, to release a new version of the
specification, including this repository layout. See the <a
href="http://www.expath.org/modules/pkg/">EXPath Packaging page</a>
for more information, and subscribe to the <a
href="http://www.expath.org/lists.html">EXPath mailing list</a> to
stay tunned.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-43614584864432527342009-11-15T20:40:00.003+01:002009-11-15T22:25:12.373+01:00EXPath Packaging System prototype implementation for Calabash<p>An interesting piece of code I worked on during the past few weeks
is the implementation of the <a
href="http://www.expath.org/modules/pkg/">EXPath Packaging System</a>
for the Norman Walsh's XProc processor: <a
href="http://xmlcalabash.com/">Calabash</a>. It was interesting for
itself, as a coding experience, but also for the still-in-development
packaging system, as XProc provides all core XML technologies within a
single language. Thus implementing the packaging system for Calabash
implied to implement it for: RNC, RNG, Schematron, XProc (for XProc
pipelines themselves,) XQuery, XSD and XSLT. This was enlightening
about the relationships between those several technologies, and a
proof of concept about the applicability of the packaging concept to
those several technologies.</p>
<p>Unfortunately, Calabash does not provide any way for the user to
finely configure the underlying processors (for instance Saxon for
XSLT, Jing for RNG, etc.) So I first needed to add this feature to
Calabash itself. Instead of plugging the EXPath stuff directly into
the Calabash code base, I decided to add only a simple API for an
external user to plug configuration code into Calabash. I hope Norm
will agree on integrating such changes into Calabash, so the packaging
support could be written entirely outside of the Calabash code base in
a first time (and maybe included in Calabash in a second time.) In
the meanwhile, you can just use <a
href="http://www.expath.org/modules/pkg/calabash-expath-r477.jar">an
alternative JAR file</a> for Calabash, including my changes (and based
on the latest Subversion revision, so this is really beta stuff,
besides some classes have been disabled also, due to dependency
issues.) You can also have a look at the <a
href="http://markmail.org/thread/rpk4z4irp3zmwbom">following email</a>
on XProc Dev with explanations on how to patch the Calabash code
base.</p>
<p>To install the packaging support for Calabash, you need to put the
following JAR files into your classpath: my <a
href="http://www.expath.org/modules/pkg/calabash-expath-r477.jar">modified
Calabash</a> JAR file, the EXPath <a
href="http://www.expath.org/modules/pkg/expath-pkg-repo-0.1.jar">repository
management</a>, the EXPath <a
href="http://www.expath.org/modules/pkg/expath-pkg-calabash-0.1.jar">packaging
support for Calabash</a> and the EXPath <a
href="http://www.expath.org/modules/pkg/expath-pkg-saxon-0.2.jar">packaging
support for Saxon</a>. Then run Calabash the usual way, besides
setting the Java property <code>org.expath.pkg.calabash.repo</code> to
the location of the repository you want to use. For repository
management, please see the next blog entry I will post here...</p>
<p>If you are under Unix (incl. Linux, Mac OS X or Cygwin under
Windows) you can use <a
href="http://www.expath.org/modules/pkg/expath-pkg-calabash-0.1.sh">this
shell script</a> to launch Calabash from the command line. Just
define the environment variable CALABASH_CP with the above classpath,
and EXPATH_REPO to the repository directory. In addition to setting
Calabash up, it will also add JAR files with extensions for Saxon
into the classpath.</p>
<p>To test if the installation is ok, install <a
href="http://www.cxan.org/tmp/invoice-1.0.xar">this sample package</a>
(wait for the next blog entry for details about installing a package
with the repository) and save the following pipeline in a file, say
invoice-test.xproc:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">p</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/ns/xproc</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">i</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.fgeorges.org/test/invoice-steps</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.fgeorges.org/test/invoice.xpl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">result</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">port</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">source</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">inline</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">invoice</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.fgeorges.org/test/invoice</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">date</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2009-10-12</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">line</span> <span class="fl-nxml-attribute-local-name">price</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">15</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">quantity</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">10</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">unitary</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.5</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">desc</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Some stuff.</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">desc</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">line</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">line</span> <span class="fl-nxml-attribute-local-name">price</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">100</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">desc</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Bigger stuff.</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">desc</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">line</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">total</span> <span class="fl-nxml-attribute-local-name">tax-excl</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">115</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">tax-incl</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">139.15</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">invoice</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">inline</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">input</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">i</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">validate</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">i</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">transform</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">p</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">declare-step</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Then run it using the above description. If you saved the shell
script under the name "calabash" in your $PATH, just type:</p>
<pre class="drkm-code-div">
calabash invoice-test.xproc
</pre>
<p>And that's all! See the <a
href="http://www.expath.org/modules/pkg/">EXPath Packaging page</a>
for more information, and subscribe to the <a
href="http://www.expath.org/lists.html">EXPath mailing list</a> to
stay tunned.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-25279803277426233092009-10-02T11:12:00.001+02:002009-11-01T14:16:41.945+01:00EXPath Packaging System prototype implementation for Saxon<h2>Introduction</h2>
<p>After having released a first implementation of <a
href="http://fgeorges.blogspot.com/2009/09/expath-packaging-system-prototype.html">EXPath
Packaging System for eXist</a>, here is a version for Saxon. You can
read this previous blog entry to get more information on the packaging
system; in particular, it says: <em>"The concept is quite simple:
defining a package format to enable users to install libraries in
their processor with just a few clicks, and to enable library authors
to provide a single package to be installed on every processors,
without the need to document (and maintain) the installation process
for each of them."</em></p>
<p>The package manager for Saxon is a graphical application (a textual
front-end will be provided soon,) and is provided as a single JAR
file. Go to the <a
href="http://www.expath.org/modules/pkg/implems.html">implementations
page</a>, or use this following <a
href="http://www.expath.org/modules/pkg/expath-pkg-saxon-0.1.jar">direct
link</a> to get the JAR. Run it as usual, for instance by
double-clicking on it or by executing the command <code>java -jar
expath-pkg-saxon-0.1.jar</code>. That will launch the package manager
window.</p>
<h2>Repositories</h2>
<p>The implementation for Saxon differs from the one for eXist in a
fundamental way: Saxon does not have a home directory where you can
put the installed packaged, and you can invoke Saxon in so many
different ways (while the eXist core is always started the same way.)
That involves two different aspects regarding package management with
Saxon: the package manager itself that installs and remove packages,
and a way to configure Saxon itself, regardless with the way you
invoke it. In addition, the homeless property of Saxon needs to
introduce the concept of package <em>repository</em>.</p>
<p>A repository is a directory dedicated to installing packages, and
should only be modified through the package manager. It contains the
packages themselves (under a form usable by Saxon) as well as
administrative informations to be able to use them (like catalogs,
etc.) The graphical package manager allows one to create a new
repository directly from the graphical interface, as well as switching
between different repositories (if you need to maintain several
repositories for several purposes.)</p>
<h2>Importing stylesheet</h2>
<p>But as I said above, having a repository full of packages is not
enough. You have to configure Saxon to use this repository. Because
you can invoke Saxon in a plenty of ways, the configuration itself is
implemented as a Java helper class that you can use in your own code
if you invoke Saxon from within Java (for instance in a Java EE web
application.) If you use Saxon from the command line, there is a
script that takes care of configuring everything for you.</p>
<p>But before looking in details at how to configure Saxon to use a
repository, let's have a look at how a stylesheet can use an installed
package. This is the whole point of the packaging system, after all.
The goal is simply to be able to use a <em>public import URI</em> in
an import statement, this URI being automatically resolved to its
local copy in the repository. Like a namespace URI is just a kind of
identifier (it is just used as a string, your processor does not try
to actually access anything at that address,) the <em>public import
URI</em> is an identifier to a specific stylesheet. This machanism
supports also having functions implemented in Java. So all you need
to do is to use this public URI, like the following:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">h</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.example.org/hello</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.example.org/hello.xsl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> ...<span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">
...
</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">h:hello('world')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>For XQuery, this is a bit different as XQuery does have a module
system. But this is actually very similar. XQuery library modules
are identified by their namespace URI. Once again, it can be seen as
a public identifier for that XQuery module. So let's say we have an
XQuery library module for the namespace URI
<code>http://www.example.org/hello</code>, then you can simply write a
module that imports it as following:</p>
<pre class="drkm-code-div">
<span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> h = <span class="fl-string">"http://www.example.org/hello"</span>;
<span class="fl-function-name">h:hello</span>('world')
</pre>
<p>And that's it! In the <em>package samples</em> section below, you
can see completes examples of such importing stylesheets and queries,
as well as the packages they use.</p>
<h2>Java configuration</h2>
<p>To configure Saxon to use a repository from Java, you need to get a
<code>Configuration</code> object. This is a central class in Saxon,
which is used almost everywhere in the Saxon code base. You can get
it from a Saxon <code>TransformerFactory</code> or from a S9API
<code>Processor</code>. With that object on the one hand, and a
<code>File</code> object pointing to the repository directory on the
other hand, you can just call:</p>
<pre class="drkm-code-div">
<span class="fl-drkm-flXcomment">// the repo directory
</span><span class="fl-type">File</span> <span class="fl-variable-name">repo</span> = ...;
<span class="fl-drkm-flXcomment">// the Saxon config object
</span><span class="fl-type">Configuration</span> <span class="fl-variable-name">config</span> = ...;
<span class="fl-drkm-flXcomment">// the EXPath Pkg configurer
</span><span class="fl-type">ConfigHelper</span> <span class="fl-variable-name">helper</span> = <span class="fl-keyword">new</span> <span class="fl-type">ConfigHelper</span>(repo);
<span class="fl-drkm-flXcomment">// actually configure Saxon
</span>helper.config(config);
</pre>
<p>Besides the Java code itself, you have to be sure 1/ to have an
actual repository at the location you pass to the
<code>ConfigHelper</code> constructor and 2/ to have the JAR files
used by and containing the extension functions written in Java into
your classpath. The only exception to this rule is when you register
such an extension function (written in Java) to Saxon 9.2; in this
case EXPath Pkg will try to dynamically add the JAR files from the
repository to the classpath. But playing with the classpath at
runtime is not something I would recommend in Java.</p>
<h2>Shell script</h2>
<p>When using Saxon from the command line, EXPath Pkg comes with an
alternate class to launch Saxon (this class automatically uses
<code>ConfigHelper</code> to configure Saxon) as well as with a shell
script to launch Saxon with the correct classpath.</p>
<p>To use this shell script (only available on Unix-like systems for
now, including Cygwin under Windows) you have to set the environment
variables <code>SAXON_HOME</code> to the directory where you put the
Saxon JAR files, <code>EXPATH_PKG_JAR</code> to the EXPath Pkg JAR
file, and <code>APACHE_XML_RESOLVER_JAR</code> to the <a
href="http://xml.apache.org/mirrors.cgi">XML Resolver JAR file</a>
from Apache. Additionally, you can set <code>EXPATH_REPO</code> to
the repository directory, to not have to explicitely give it as an
option each time you invoke Saxon. If all the above environment
variables have been correctly set, and the script added to your PATH,
you can just invoke Saxon as usual: <code>saxon -s:source.xml
-xsl:stylesheet.xsl</code>.</p>
<p>Use <code>saxon --help</code> to get the usage help of this script.
You can set the EXPath repository (and thus override
<code>EXPATH_REPO</code> if it is set) with the option
<code>--repo=</code>. You can add items to the classpath with the
option <code>--add-cp=</code>. You can set the classpath (so
overriding <code>SAXON_HOME</code> and other environment variables)
with the option <code>--cp=</code>. The script detects if Saxon SA is
present, and if so will use the SA version. You can force either B or
SA version with either <code>--b</code> or <code>--sa</code>. You can
also set any option to the Java Virtual Machine by using
<code>--java=</code>, for instance to set a system property, and
<code>--mem=</code> to set the amount of memory of the virtual machine
(shortcut for the Java option -Xmx) And finally, you can also set the
HTTP and HTTPS proxy information with <code>--proxy=host:port</code>
(for instance <code>--proxy=proxyhost:8080</code>.)</p>
<h2>Package samples</h2>
<p>The <a
href="http://www.fgeorges.org/purl/20091002/functx-1.0.xar">first
example</a> is a packaged version of Priscilla Walmsley's <a
href="http://www.functx.com/">FunctX</a>. This package contains both
the XSLT and the XQuery versions of this library. Of course, the
XQuery module defines a module namespace, but the XSLT stylesheet does
not have any public import URI (as this is behind the standard.) I
chose the URI <code>http://www.functx.com/functx-1.0.xsl</code>, but
keep in mind this is not <em>official</em> by any means, this is just
the URI I chose. It is intended that library authors package their
own libraries and choose the public URIs themselves.</p>
<p>The package itself is a plain ZIP file. If you open it or unzip it
with your preffered tool, you can see that at the top level, there is
a file named <code>expath-pkg.xml</code>. This is the <em>package
descriptor</em>, that defines what the package contains (at least what
is publicly exported from the package, so what can be used from within
a stylesheet or a query.) In the case of this FunctX package, this
descriptor looks like:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">package</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://expath.org/mod/expath-pkg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">module</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">functx</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">FunctX library for XQuery 1.0 and XSLT 2.0</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">xsl</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">import-uri</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://www.functx.com/functx-1.0.xsl</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">import-uri</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">functx-1.0-doc-2007-01.xsl</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">xsl</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">xquery</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">namespace</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://www.functx.com</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">namespace</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">functx-1.0-doc-2007-01.xq</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">xquery</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">module</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">package</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>To install the package, just download it to a temporary location,
launch the package manager as explained at the beginning of this blog
post, choose "install" in the file menu, and choose the package on
your filesystem. To test if it is correctly installed, write the
following stylesheet:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">f</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.functx.com</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.functx.com/functx-1.0.xsl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">/</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">result</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:date(1979, 9, 1)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">result</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>and/or the following XQuery main module (depending on what you want
to test):</p>
<pre class="drkm-code-div">
<span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> f = <span class="fl-string">"http://www.functx.com"</span>;
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">resul</span><span class="fl-nxml-element-local-name">t</span><span class="fl-nxml-tag-delimiter">></span> {
<span class="fl-function-name">f:date</span>(1979, 9, 1)
}
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">resul</span><span class="fl-nxml-element-local-name">t</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>To evaluate them, make sure you configured the shell script
correctly, as explained above, then open a shell and type one of the
following command (or both) where style.xsl is the file where you
saved the above stylesheet and query.xq is the file where your saved
the above query:</p>
<pre class="drkm-code-div">
$ saxon -xsl:style.xsl -it:main
<result>1979-09-01</result>
$ saxon --xq query.xq
<result>1979-09-01</result>
$
</pre>
<p>If you prefer to test from Java, just write a simple main class
that evaluates the above stylesheet and/or query, taking care of using
<code>ConfigHelper</code> to set up the Saxon <code>Configure</code>
object. For instance, if you want to use the S9API, you can configure
the <code>Processor</code> object like the following (don't forget to
add the EXPath Pkg and the Apache XML resolver JAR files to your
classpath):</p>
<pre class="drkm-code-div">
<span class="fl-drkm-flXcomment">// the repo directory
</span><span class="fl-type">File</span> <span class="fl-variable-name">repo</span> = <span class="fl-keyword">new</span> <span class="fl-type">File</span>(<span class="fl-string">"..."</span>);
<span class="fl-drkm-flXcomment">// the EXPath Pkg configurer
</span><span class="fl-type">ConfigHelper</span> <span class="fl-variable-name">helper</span> = <span class="fl-keyword">new</span> <span class="fl-type">ConfigHelper</span>(repo);
<span class="fl-drkm-flXcomment">// the Saxon processor
</span><span class="fl-type">Processor</span> <span class="fl-variable-name">proc</span> = <span class="fl-keyword">new</span> <span class="fl-type">Processor</span>(<span class="fl-constant">false</span>);
<span class="fl-drkm-flXcomment">// actually configure Saxon
</span>helper.config(proc.getUnderlyingConfiguration());
<span class="fl-drkm-flXcomment">// then use 'proc</span><span class="fl-warning">'</span><span class="fl-drkm-flXcomment"> as usual...
</span>
</pre>
<p>The <a
href="http://www.fgeorges.org/purl/20091002/test-ext-saxon-0.1.xar">second
sample package</a> provides a single function:
<code>ext:hello($who)</code>. It is written in Java. Besides other
stuff related to the packaging itself, it contains a JAR file with the
implementation of that extension function. To test it, just follow
the same steps as for the FunctX package, except that you have to add
the installed JAR file (from within the repository) to your claspath
(this is done automatically for you if you use the shell script, but
not if you test it from a Java program.)</p>
<h2>Conclusion</h2>
<p>This is just a prototype implementation of a package manager for
Saxon, which is consistent with <a
href="http://fgeorges.blogspot.com/2009/09/expath-packaging-system-prototype.html">the
one for eXist</a>. The main issue is the configuration of the
classpath, but I think this is best let to the user than having to
deal with the classpath, in particular within the context of a Java EE
application. This issue shows up also in your IDE configuration. For
now, I configure oXygen by adding the catalogs from the repository to
the oXygen's main catalog list, and the extension JAR files to the
oXygen classpath, so the built-in Saxon processors can be used exactly
as usual. But such issues can be resolved by native support right into
the processors ad IDEs.</p>
<p>Besides this classpath issue, I am convinced that package
management will really improve the current situation, and maybe could
be the missing piece to distribute real general-purpose libraries for
XQuery and XSLT, and one of the basis to other systems, like an
implementation-independent XRX system.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-50215082260274094782009-09-12T20:11:00.006+02:002009-09-12T20:15:39.057+02:00EXPath Packaging System prototype implementation for eXist<p>During the past few weeks, I have been working on the <a
href="http://www.expath.org/modules/pkg/">Packaging System</a> for <a
href="http://www.expath.org/">EXPath</a> (see also this <a
href="http://fgeorges.blogspot.com/2009/06/divide-and-conquer-or-xpath-xslt-xquery.html">blog
entry</a> for more info.) The concept is quite simple: defining a
package format to enable users to install libraries in their processor
with just a few clicks, and to enable library authors to provide a
single package to be installed on every processors, without the need
to document (and maintain) the installation process for each of
them.</p>
<p>Of course, this system should be supported right into the
processors themselves, as this is intimately related to the way each
processor manages its queries and/or stylesheets. But to convince
vendors, we first have to show something that does work, and to show
that users are actually interested. So I have written a prototype
implementation for eXist (as well as one for Saxon, but it still needs
some cosmetic work in order to be released.)</p>
<p>The package manager for eXist is a graphical application (a textual
front-end will be provided soon,) and is provided as a single JAR
file. Go to the <a
href="http://www.expath.org/modules/pkg/implems.html">implementations
page</a>, or use this following <a
href="http://www.expath.org/modules/pkg/expath-pkg-exist-0.1.jar">direct
link</a> to get the JAR. Run it as usual, for instance by
double-clicking on it or by executing the command <code>java -jar
expath-pkg-exist-0.1.jar</code>. That will launch the package manager
window.</p>
<p>The manager acts on an eXist <em>instance</em>, that is, the
directory where you installed eXist on your machine (the one that
contains the <code>conf.xml</code> file.) You can have several
instances installed on a same computer, but the package manager only
acts on a single one at a time. You can select it via the
<code>File</code> menu, item <code>Open instance</code>. Just select
the correct directory. By default, if the environment variable
<code>EXIST_HOME</code> is set, the manager will use this directory.
If not, it will display a warning and wait for you to select an
instance:</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho99lVF8clfuXpdop0-qcWOtiJz64ad-w8tmZKDOaYy7tH6oGvB-k83bfWVYDngRyUTxYaLldIBW8HYbc8hZOos9vRAOn1a_ngp3YLSQvXqgRHXQPbNaNjPxPJfN6dwgvhzuE6iA/s1600-h/pkg-mgr-exist-01.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 136px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEho99lVF8clfuXpdop0-qcWOtiJz64ad-w8tmZKDOaYy7tH6oGvB-k83bfWVYDngRyUTxYaLldIBW8HYbc8hZOos9vRAOn1a_ngp3YLSQvXqgRHXQPbNaNjPxPJfN6dwgvhzuE6iA/s400/pkg-mgr-exist-01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5380645554073936322" /></a>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkticwJR5cEp8A1v6WQMZeOOWdAW3RmGWsM7gWAwTvsaaeV0wabmQu1W6qCNfNTmDKRwWJ8kDcwQbcH7LYdbwr_7ELHEFsCgWD0Skn-faUJo5QxFtsfGo3naUwBkBgFy72FSuKTQ/s1600-h/pkg-mgr-exist-02.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 288px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkticwJR5cEp8A1v6WQMZeOOWdAW3RmGWsM7gWAwTvsaaeV0wabmQu1W6qCNfNTmDKRwWJ8kDcwQbcH7LYdbwr_7ELHEFsCgWD0Skn-faUJo5QxFtsfGo3naUwBkBgFy72FSuKTQ/s400/pkg-mgr-exist-02.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5380645675515353842" /></a>
<p>The manger stores some info in a file created in the instance
directory. If this file does not exist, the manager asks you to
confirm to create it. That is kind of initializing this instance for
the EXPath Packaging system. You can safely answer yes:</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7A5_j5gixnZ4m9x683ECtuMURaUVQkGigUGwrJvvsSXEL2V_9fosX4TkMfkc2dE3m28d6-oX84_pFeJrjmAgG8xgrUKzUI__3vHek2lH3rNwDY9W3rvPTLg6VH6Q3TBCaDsczOQ/s1600-h/pkg-mgr-exist-03.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 119px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7A5_j5gixnZ4m9x683ECtuMURaUVQkGigUGwrJvvsSXEL2V_9fosX4TkMfkc2dE3m28d6-oX84_pFeJrjmAgG8xgrUKzUI__3vHek2lH3rNwDY9W3rvPTLg6VH6Q3TBCaDsczOQ/s400/pkg-mgr-exist-03.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5380645769951181458" /></a>
<p>Once an eXist instance is selected, the manager shows a list of the
packages installed in this instance. Using the menu, you can deleting
a package previously installed, or install a new one. To install a
new package, you have to select it through the file selection dialog.
Package files have the <code>*.xar</code> extension.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDfDSkscVzijm6WFlUjybQPogfL5uui7Wa2rfk5mikngvIrhDyuqL7wr7v8FM-PCb_vIu2yDwlXKdfcG_GM8FcaGM2n4C36XhJGFnQdrLRWz0Y-ZMAafi7Makhv5QBq_ruLdDIbA/s1600-h/pkg-mgr-exist-04.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 288px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDfDSkscVzijm6WFlUjybQPogfL5uui7Wa2rfk5mikngvIrhDyuqL7wr7v8FM-PCb_vIu2yDwlXKdfcG_GM8FcaGM2n4C36XhJGFnQdrLRWz0Y-ZMAafi7Makhv5QBq_ruLdDIbA/s400/pkg-mgr-exist-04.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5380645875510128514" /></a>
<p>In order to test the system, you can use the following packages.
The <a
href="http://www.fgeorges.org/purl/20090911/functx-xq-1.0.xar">first
one</a> is actually nothing else than Priscilla Walmsley's <a
href="http://www.functx.com/">FunctX</a> for XQuery, that I packaged
(just because this is a more interesting and useful example of a
library written in standard XQuery than a simple <em>hello world</em>
example...) The <a
href="http://www.fgeorges.org/purl/20090911/exist-specific-0.1.xar">second
one</a> is a simple XQuery module that use eXist extension functions
(remember that a XAR is simply a ZIp file, so you can open it and see
the actual XQuery file within it.) Technically, it is deployed
exactly as a standard XQuery file, but in the package it is flagged as
dependent on eXist. And the <a
href="http://www.fgeorges.org/purl/20090911/test-ext-0.1.xar">last
one</a> is a simple module written in Java. It provides a simple
function that says hello.</p>
<p>If you want to test the installation, start your eXist instance (or
restart it, but I would say it is safer to stop it to install
packages) and try one of those queries:</p>
<pre class="drkm-code-div">
<span class="fl-comment">(: test the first package: FunctX... :)</span>
<span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> f = <span class="fl-string">"http://www.functx.com"</span>;
<span class="fl-function-name">f:date</span>(1979, 9, 1)
<span class="fl-comment">(: ...or test the second package... :)</span>
<span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> v = <span class="fl-string">"http://www.example.com/version"</span>;
<span class="fl-function-name">v:info</span>()
<span class="fl-comment">(: ...or test the third package :)</span>
<span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> t = <span class="fl-string">"http://www.example.com/ext"</span>;
<span class="fl-function-name">t:hello</span>('you')
</pre>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6rnlSjBR9adOn6mF4K9ArdP4C86lXjp7a0AyIdofE9_DH0HrXdEkzN4xnkIwPjgYJlJYUd8LoXy953LGayILWoITywK_aygF_dinsYZkjC39KM159ldUul6wMM0NdRx566vhH6A/s1600-h/pkg-mgr-exist-05.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 383px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6rnlSjBR9adOn6mF4K9ArdP4C86lXjp7a0AyIdofE9_DH0HrXdEkzN4xnkIwPjgYJlJYUd8LoXy953LGayILWoITywK_aygF_dinsYZkjC39KM159ldUul6wMM0NdRx566vhH6A/s400/pkg-mgr-exist-05.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5380645993133007410" /></a>
<p>How does it work? The easiest is maybe to open the XAR files and
see what they contain. For instance, the package for FunctX contains
(when opened as a ZIP file) a file <code>expath-pkg.xml</code> and a
file <code>functx/functx-1.0-doc-2007-01.xq</code>. The later is
simply the XQuery file, exactly as you can find it on the <a
href="http://www.functx.com/">FunctX</a> website. The former is the
<em>package descriptor</em>. This is a little XML file describing the
content of the package. In this case, it contains:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">package</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://expath.org/mod/expath-pkg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">module</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">functx</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">FunctX library for XQuery 1.0</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">xquery</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">namespace</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://www.functx.com</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">namespace</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">functx-1.0-doc-2007-01.xq</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">xquery</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">module</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">package</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>You can see that this descriptor contains the name of the library
(here <em>functx</em>) as well as a user-friendly title, and its
version number. Then the XQuery file is registered with its target
namespace. This info is used by the manager to update the eXist's
<code>conf.xml</code> file. The actual XQuery file is wrapped in a
JAR file that is put in the eXist classpath, to enable eXist to find
it as a resource. If you open the package descriptor of the 2 other
packages, you will discover that they are slightly different (to
differenciate the different kinds of libraries, in particular those
written in Java.)</p>
<p>If you have any comment, idea or criticism, please tell us on the
EXPath <a href="http://www.expath.org/lists.html">mailing list</a>. I
hope to release the package manager for Saxon quite soon, I will
announce it on the list.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-33537505575848923542009-07-31T23:55:00.007+02:002009-08-01T00:02:26.676+02:00eXist extension functions in Java<p>Investigating into opportunities for an implementation of <a
href="http://fgeorges.blogspot.com/2009/06/divide-and-conquer-or-xpath-xslt-xquery.html">EXPath
Packaging</a> for <a href="http://www.exist-db.org/">eXist</a>, I am
looking at the way to implement extension functions with Java. I
detail here the key points I found to write Java extensions for eXist
using NetBeans. But those info should be generic enough to be used
with any Java IDE.</p>
<p>If you want to provide an extension function written in Java within
eXist, you actually have to provide a full module in Java. You cannot
provide the module part in XQuery and part in Java (though you can
provide an XQuery module that imports a private module written in
Java.)</p>
<p>The module is represented by a class that extends the eXist abstract
class <a
href="http://www.exist-db.org/api/org/exist/xquery/AbstractInternalModule.html">AbstractInternalModule</a>.
Along some information like the namespace URI of the module, the
default prefix to use, and a description, you have to provide a list
of extension functions through the base class constructor:</p>
<pre class="drkm-code-div"><span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">SimpleModule</span> <span class="fl-keyword">extends</span> <span class="fl-type">AbstractInternalModule</span>
{
<span class="fl-keyword">public</span> SimpleModule() {
<span class="fl-keyword">super</span>(FUNCTIONS);
}
<span class="fl-keyword">public</span> <span class="fl-type">String</span> <span class="fl-function-name">getNamespaceURI</span>() {
<span class="fl-keyword">return</span> NAMESPACE_URI;
}
<span class="fl-keyword">public</span> <span class="fl-type">String</span> <span class="fl-function-name">getDefaultPrefix</span>() {
<span class="fl-keyword">return</span> PREFIX;
}
<span class="fl-keyword">public</span> <span class="fl-type">String</span> <span class="fl-function-name">getDescription</span>() {
<span class="fl-keyword">return</span> <span class="fl-string">"A simple example module"</span>;
}
<span class="fl-keyword">static</span> <span class="fl-keyword">final</span> <span class="fl-type">String</span> <span class="fl-variable-name">PREFIX</span> = <span class="fl-string">"ext"</span>;
<span class="fl-keyword">static</span> <span class="fl-keyword">final</span> <span class="fl-type">String</span> <span class="fl-variable-name">NAMESPACE_URI</span> = <span class="fl-string">"http://www.example.org/project/ext"</span>;
<span class="fl-keyword">private</span> <span class="fl-keyword">final</span> <span class="fl-keyword">static</span> <span class="fl-type">FunctionDef</span>[] <span class="fl-variable-name">FUNCTIONS</span> = {
<span class="fl-keyword">new</span> <span class="fl-type">FunctionDef</span>(<span class="fl-constant">SimpleFunction</span>.SIGNATURE, SimpleFunction.<span class="fl-keyword">class</span>)
};
}</pre>
<p>This module contains one single function, implemented by the class
<code>SimpleFunction</code>. An extension function is a Java class
that extends the eXist abstract class <a
href="http://www.exist-db.org/api/org/exist/xquery/BasicFunction.html">BasicFunction</a>.
It has to provide some information to the base class constructor (its
qualified name, a documentation string, its parameter list and its
return type.) The logic of the function itself is located in the
<a
href="http://www.exist-db.org/api/org/exist/xquery/BasicFunction.html#eval(org.exist.xquery.value.Sequence[], org.exist.xquery.value.Sequence)">eval</a>
function:</p>
<pre class="drkm-code-div"><span class="fl-drkm-flXcomment">// implements </span><span class="fl-type">the</span><span class="fl-drkm-flXcomment"> function "ext:hello($who as xs:string) as element()</span><span class="fl-warning">"</span><span class="fl-drkm-flXcomment">.
</span><span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">SimpleFunction</span> <span class="fl-keyword">extends</span> <span class="fl-type">BasicFunction</span>
{
<span class="fl-keyword">public</span> SimpleFunction(<span class="fl-type">XQueryContext</span> <span class="fl-variable-name">ctxt</span>) {
<span class="fl-keyword">super</span>(ctxt, SIGNATURE);
}
<span class="fl-drkm-flXcomment">/** return an element <hello> with the value of the string param as content */</span>
<span class="fl-keyword">public</span> <span class="fl-type">Sequence</span> <span class="fl-function-name">eval</span>(<span class="fl-type">Sequence</span>[] <span class="fl-variable-name">args</span>, <span class="fl-type">Sequence</span> <span class="fl-variable-name">unused</span>) <span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span> {
<span class="fl-type">String</span> <span class="fl-variable-name">type</span> = Integer.toString(args[0].getItemType());
<span class="fl-type">MemTreeBuilder</span> <span class="fl-variable-name">builder</span> = context.getDocumentBuilder();
builder.startDocument();
builder.startElement(<span class="fl-keyword">new</span> <span class="fl-type">QName</span>(<span class="fl-string">"hello"</span>, <span class="fl-constant">null</span>, <span class="fl-constant">null</span>), <span class="fl-constant">null</span>);
builder.characters(args[0].getStringValue());
builder.endElement();
builder.endDocument();
<span class="fl-keyword">return</span> (<span class="fl-type">Sequence</span>) builder.getDocument().getDocumentElement();
}
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-keyword">final</span> <span class="fl-type">FunctionParameterSequenceType</span> <span class="fl-variable-name">PARAM_WHO</span> =
<span class="fl-keyword">new</span> <span class="fl-type">FunctionParameterSequenceType</span>(<span class="fl-string">"who"</span>, <span class="fl-constant">Type</span>.STRING, <span class="fl-constant">Cardinality</span>.EXACTLY_ONE, <span class="fl-string">"Who?"</span>);
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-keyword">final</span> <span class="fl-type">FunctionReturnSequenceType</span> <span class="fl-variable-name">RETURN_TYPE</span> =
<span class="fl-keyword">new</span> <span class="fl-type">FunctionReturnSequenceType</span>(<span class="fl-constant">Type</span>.ELEMENT, <span class="fl-constant">Cardinality</span>.EXACTLY_ONE, <span class="fl-string">"Hello element"</span>);
<span class="fl-keyword">static</span> <span class="fl-keyword">final</span> <span class="fl-type">FunctionSignature</span> <span class="fl-variable-name">SIGNATURE</span> = <span class="fl-keyword">new</span> <span class="fl-type">FunctionSignature</span>(
<span class="fl-keyword">new</span> <span class="fl-type">QName</span>(<span class="fl-string">"hello"</span>, <span class="fl-constant">SimpleModule</span>.NAMESPACE_URI, <span class="fl-constant">SimpleModule</span>.PREFIX),
<span class="fl-string">"Return greetings."</span>
+ <span class="fl-string">" This method returns an element 'hello' with the name passed as param."</span>,
<span class="fl-keyword">new</span> <span class="fl-type">SequenceType</span>[] { PARAM_WHO },
RETURN_TYPE
);
}</pre>
<p>In order to compile those files with NetBeans, you have to add two JAR
files to the build path of the project you used for those files.
Right-click on the project and choose <code>Properties</code>, then
<code>Libraries</code> and the button <code>Add JAR/Folder</code>.
You will find the JARs in the eXist install directory:
<code>$EXIST_HOME/exist.jar</code> and
<code>$EXIST_HOME/lib/core/xmldb.jar</code>. Then you compile your
project to get the JAR file with your both class (the module and its
single function) compiled. The best choice for the project's type is
a library of Java classes.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnK5TMqIMgLyxPKkQB_DNC3fG_NeMKUkgsu2PtDFOC4MNPmo_czbPqJgJqPn-chL9-apPMF7vtaHR75skFEsba6xFhfFyMhUJvo7Y18I7SHEVYow-4GvJVPRPQNdfRJit_8Qs55g/s1600-h/Picture+5.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 300px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnK5TMqIMgLyxPKkQB_DNC3fG_NeMKUkgsu2PtDFOC4MNPmo_czbPqJgJqPn-chL9-apPMF7vtaHR75skFEsba6xFhfFyMhUJvo7Y18I7SHEVYow-4GvJVPRPQNdfRJit_8Qs55g/s400/Picture+5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5364746485706833778" /></a>
<p>Now you have the JAR file containing the Java implementation of your
module and its function. The next step is to plug them within an
eXist instance. Copy the JAR file to
<code>$EXIST_HOME/lib/extensions/</code> and configure it in
<code>$EXIST_HOME/conf.xml</code>. The configuration only requires to
add a new <code>module</code> element to the
<code>builtin-modules</code> element:</p>
<pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">module</span> <span class="fl-nxml-attribute-local-name">class</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">org.example.project.SimpleModule</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">uri</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.example.org/project/ext</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span></pre>
<p>Just restart your eXist instance, and try the following query in the
admin console:</p>
<pre class="drkm-code-div"><span class="fl-keyword">import</span> <span class="fl-keyword">module</span> <span class="fl-keyword">namespace</span> <span class="fl-nxml-attribute-prefix">ex</span><span class="fl-nxml-attribute-local-name">t</span>=<span class="fl-string">"http://www.example.org/project/ext"</span>;
<span class="fl-function-name">ext:hello</span>('you')</pre>
<p>This will call the method eval on a <code>SimpleFunction</code>
object, discovered through a <code>SimpleModule</code> object
configured in <code>conf.xml</code>. Soon, you should be able to
package the JAR file to an EXPath package and install it within eXist
through a graphical console...</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-77503562602861535842009-06-25T01:56:00.013+02:002009-07-14T13:34:40.560+02:00Divide and Conquer, or XPath, XSLT, XQuery and XProc packaging<p>Packaging of various X* technologies seems to be of interest for a lot
of people for now. And of course it is for me. But it seems everyone
comes with its own idea of packaging, as well as a different scope.
So to add to the complexity yet, I will present here my own ideas on
that matter. Hopefully, I will try to tidy up the different concepts
and to identify the different needs. And as always, I like to speak
about concrete. To ease further discussions, if only that. So I will
introduce a prototype of a packaging system for X* libraries and
extensions for Saxon.</p>
<p>Packaging is nothing in itself. It is always related to something
else (a language, a technology, a framework...) Packaging is just a
mean to ease sharing and delivering something in the scope of that
"something else." The several files in an ODF document are packaged
in a single ZIP file, with a pre-defined structure, to make it
possible for an application to use its content. The important point
is not the structure in itself, but rather the information it gathers.</p>
<p>I have followed some very interesting discussions about X* packging
during the last few weeks, with very interesting people. Rapidly, I
have seen everyone were talking about slightly (or not) different
things. The most important point where people have different views
IMHO, is the scope of packaging.</p>
<p>As with most of modern languages, an XML developer may have to deliver
different pieces of software, depending on the project: libraries,
standalone applications, or web applications built for a specific
framework. If you look at Java for instance, this is reflected quite
clearly in its various packaging formats: JAR files for libraries and
applications, WAR files for web applications, EAR files for entire
enterprise applications...</p>
<p>WAR files contain Java classes, as JAR files. But the structure is
quite different, and there are a few other files, describing what is
in the package: "that class is a servlet class, conforming to the
definition of servlet and coded to live in a servlet container, with a
precise lifecycle," or "the package depends on this JAR file."</p>
<p>The same way, you can package XSLT libraries or XQuery modules,
telling a processor that when a stylesheet or a module imports a
specific URI, some functions are available (provided as plain XSLT
stylesheets, XQuery modules, or extension functions.) Or you can
package an entire web application using XProc to control the overall
processes, XQuery to query XML databases and XSLT for the presentation
layer (sounds very MVC, doesn't it?) But those packages are really
different beasts: when the first example just need to package some
XSLT, XQuery, Java, whatever code, alonside a simple cataloging
system, the second example require to define a complete web framework,
its lifecycle, how script can plug into this and exchange information
with it ("this XProc pipeline has to be evaluated on an HTTP GET on
http://www.example/app/theuri, it knows you will provide it with
request information as a wa:http-request element, as we agreed upon,
and that XSLT stylesheet has to be applied to its result; by the way
it will access runtime information by using the extension functions
you provide.")</p>
<p>There has been some work on XRX frameworks, and clearly it would be
beneficial for anybody (users, but also implementors,) to have such a
standard packaging format for entire applications following their
rules (as WAR and EAR files can be to Java.) And they would benefit
also from a more low-level packaging format dedicated to package X*
libraries, and would build upon them. But they really are at
different levels, and I think it is fundamental to make the
distinction between both concepts.</p>
<p>As part of the <a href="http://www.expath.org/">EXPath</a> project, and because I think this is the first
step X* technologies need for several years to enable the delivery of
libraries, I am particularly interested in a library packaging
format.</p>
<p>To illustrate that, I've built a very simple prototype of a package
manager for Saxon. On the one hand you have a simple GUI to install
and delete packages in a repository, and on the other hand you have a
shell script to launch Saxon (setting the classpath for extension
functions and setting catalogs to resolve XSLT imports refering to
libraries.) If those tools are built around a well-defined, open
package format, other implementations could be written (for eXist, for
MarkLogic, XQilla, Zorba... but also for oXygen, providing a one-click
implementation to install a package and then being able to enable it
in some scenarii.)</p>
<p>You can find the manager at <a href="http://www.fgeorges.org/purl/20090624/">http://www.fgeorges.org/purl/20090624/</a>.
You should be able to run it simply by clicking on one of the links on
the launch.html page (through Java Web Start,) but you can also
download the JAR file (look also in the lib/ sub-directory,) putting
both JAR files in the classpath and running Java the usual way, with
the main class org.expath.pkg.saxon.PackageManagerGUI (there is also a
text interface with org.expath.pkg.saxon.PackageManagerTextUI.) You
first have to set up an environment variable EXPATH_REPO, pointing to
a directory (that will be your EXPath Packaging repository, just
create an empty directory.) The interface is very simple: choose the
install item in the file menu, and select the package file you want to
install. To remove a package, select it in the list of installed
modules and select delete in the menu.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS8g5IiPb5rwaUmWLR6MyX29IY14su5Sqwb3s9oVTCmFLDnatMUBhQ2lhjj3VSniSDEvxRg5W9Y26LO3mhLauPp-EVfwcHKk60vH2o0hVKxK6hyOvXLmLGK-JsFHvPM6EpEHss-Q/s1600-h/Picture+6.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 236px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjS8g5IiPb5rwaUmWLR6MyX29IY14su5Sqwb3s9oVTCmFLDnatMUBhQ2lhjj3VSniSDEvxRg5W9Y26LO3mhLauPp-EVfwcHKk60vH2o0hVKxK6hyOvXLmLGK-JsFHvPM6EpEHss-Q/s400/Picture+6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5351047856225134274" /></a>
<p>Once a module is installed, you can use it via Saxon by adding the
additional JARs to the classpath as needed (for extension functions)
and by setting up the XML Catalogs support. The following script does
that for you: <a href="http://www.fgeorges.org/purl/20090624/saxon">http://www.fgeorges.org/purl/20090624/saxon</a>. It needs a
few environment variables: EXPATH_REPO as explained above,
APACHE_XML_RESOLVER_JAR must point to the Apache XML Commons Resolver
(see <a href="http://xml.apache.org/commons/">http://xml.apache.org/commons/</a>, and be sure to pick the resolver
JAR) and SAXON_HOME must point to the directory containing the Saxon
JARs.</p>
<p>But what about the package format itself? In this prototype, this is
a simple ZIP file, with the following structure:</p>
<pre class="drkm-code-div">
expath-pkg.xml
expath-http-client/
saxon/
xsl/
expath-http-client-saxon.xsl
jar/
expath-http-client-saxon.jar
lib/
commons-codec-1.3.jar
...jar
</pre>
<p>where expath-pkg.xml is the package descriptor, and expath-http-client
is the directory containing one module (here the EXPath HTTP Client
module.) This module is implemented as a Java extension, besides a
frontend XSLT stylesheet that take care of Saxon-specifics to bind to
the Java functions. During the install, an XML Catalogs file is
created, to resolve the URI http://www.expath.org/mod/http-client.xsl
to that stylesheet, in the local repository. One stylesheet can then
simply import that URI and use the functions of the module. The real
package for the HTTP Client can be downloaded at the same place:
<a href="http://www.fgeorges.org/purl/20090624/expath-http-client-saxon-0.3.zip">http://www.fgeorges.org/purl/20090624/expath-http-client-saxon-0.3.zip</a>.</p>
<p>There are of course still a lot of work defining exactly the package
format, how to handle dependencies, improving the implementation...
But I think that gives the big picture. If you are interested, here
is what the package descriptor looks like:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">package</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://expath.org/mod/expath-pkg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">module</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">0.3</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">expath-http-client</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">EXPath HTTP Client</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">xsl</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">import-uri</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://www.expath.org/mod/http-client.xsl</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">import-uri</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">saxon/xsl/expath-http-client-saxon.xsl</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">file</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">xsl</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">module</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">package</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>We can see the package contains one module, namely "EXPath HTTP
Client," version 0.3. The URIs are used to create an XML catalog.
This version of the package contains all the dependencies (the JARs
used by the Java implementation of the extension functions,) but they
can be also left out, and configured with the following element:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">saxon</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dep</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">jar</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Apache Commons Codec 1.3</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://jakarta.apache.org/commons/codec/</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">dep</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dep</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">jar</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Apache Commons Logging 1.1.1</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://commons.apache.org/logging/</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">dep</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dep</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">jar</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Apache HTTP Client 4.0-beta2</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://hc.apache.org/</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">dep</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dep</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">jar</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Apache HTTP Core 4.0</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://hc.apache.org/</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">dep</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dep</span> <span class="fl-nxml-attribute-local-name">type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">jar</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Tagsoup 1.2</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://home.ccil.org/~cowan/XML/tagsoup/</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">home</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">href</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">http://home.ccil.org/~cowan/XML/tagsoup/tagsoup-1.2.jar</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">href</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">dep</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">saxon</span><span class="fl-nxml-tag-delimiter">>
</span>
</pre>
<p>The GUI does not take them into account yet, but it should propose to
automatically download JARs when possible, and give the user a list of
libraries and their homepage when a manual download is required. But
of course, the same format can be used to package standard XSLT
stylesheets, without any Java features, just by mapping the main entry
point files to their public URIs.</p>
<p>Of course, this format will be particularly useful once precisely
defined in an open spec, and if several processors support it (either
natively, or through external managers.)</p>
<p>To end this post, I would like to introduce an idea from Jim Fuller:
CXAN. I am sure most of you know CTAN for TeX, or CPAN for Perl.
They are central, organized repositories of libraries for those
languages, accessible throught HTTP. With a proper packaging format,
it would be possible to set up such a web repository gathering XPath,
XSLT, XQuery and XProc libraries and applications, installable
automatically with a manager that would install a package from its
name, handling dependencies and the like. But for sure, that is yet a
step forward.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com4tag:blogger.com,1999:blog-33074681.post-16866054684922345112009-03-21T15:01:00.006+01:002009-06-25T02:21:36.320+02:00SOA Design Patterns and Web Service Contract Design & Versioning for SOA<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHoDFfY_RQSAr6MmAJv_7n9DqruErtSdNgf0eqLB2_9kCLUw38Ap_Yn_J_wwfQyEGkBZy7LiOdjnUMmYVdO2xhidNHyBm5b3FjCKGtKI60sTFf8TBwGaGpIAkj1ousnYq_QbP8RA/s1600-h/soa-patterns.jpg"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 151px; height: 200px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHoDFfY_RQSAr6MmAJv_7n9DqruErtSdNgf0eqLB2_9kCLUw38Ap_Yn_J_wwfQyEGkBZy7LiOdjnUMmYVdO2xhidNHyBm5b3FjCKGtKI60sTFf8TBwGaGpIAkj1ousnYq_QbP8RA/s200/soa-patterns.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5315641456569263186" /></a>
<p>A few weeks ago, I received the final, paper version of the book "<em>SOA
Design Patterns</em>" that I contributed to. I was used to the drafts, and I
am glad to say the final layout is really nice. Same for the previous
book, "<em>Web Service Contract Design & Versioning for SOA</em>." More info
at <a href="http://www.soapatterns.com/">http://www.soapatterns.com/</a> and <a href="http://www.soabooks.com/">http://www.soabooks.com/</a>.Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-55344687205871058542009-02-27T13:14:00.004+01:002009-02-27T13:41:18.425+01:00XSLStyle and oXygen<p>On almost every XSLT projects I worked on, I used Ken Holman's <a
href="http://www.cranesoftwrights.com/resources/xslstyle/">XSLStyle</a><sup>TM</sup>.
It enables one to document each stylesheet component (template,
function, variable, module, etc.) using an XML vocabulary (<a
href="http://www.docbook.org/">DocBook</a> and <a
href="http://dita.xml.org/">DITA</a> are supported out of the box.)
For instance, the following exerpt shows how to document a simple
named template with a parameter, assuming the vocabulary has been set
to DocBook:</p>
<pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">doc</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">para</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Create a paragraph with a greetings message.</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">para</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">doc</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">who</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">para</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">The name of the person to address the greetings to.</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">para</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">doc</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">doc</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">greetings</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">who</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:string</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">h</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">p</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">concat('Hello, ', $who, '!')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">h</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">p</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span></pre>
<p>XSLStyle<sup>TM</sup> is a set of stylesheets to extract this
information and format it to an HTML page. Besides this formating
tasks, it also checks for best-practices (did you declare the type for
parameters?, etc.) I think this is a very important piece in the XSLT
writer's toolbox.</p>
<p>Seting a project up to use XSLStyle is as easy as adding a tranform
task using the XSLStyle's stylesheets to transform the project's
stylesheet to HTML pages. And of course to add documentation to the
stylesheets. All that is very easy, but you always have to remember
where to installed XSLStyle, check for the namespace URIs to use, and
the exact element names to use to document your code. Once again,
that's very easy, but repetitive and time-consuming.</p>
<p>I use <a href="http://www.oxygenxml.com/">oXygen</a> more and more for
a few months. And I really enjoy it. It helps a lot automating
repetitive, time-consuming tasks: create a new stylesheet with the
right namespace URIs, code completion for known vocabularies, tansform
scenarii, etc. And for schemas, XQuery modules and WSDL definitions,
it provides actions to generate documentation, the same way XSLStyle
generates documentation for XSLT modules. Unfortunately, it does not
support XSLStyle yet. Actually, the scenario attached to almost all
of my stylesheets is the scenario using XSLStyle.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGlom4WrMXyHVC55Ve3CjWHTgWqq2KEBXExMDmblmEaZkPCav_E5kEpvfkamuowpCYVHxsilmJKMpWugEuahhXjWsNJNleN81Js1TPmDXdzv8fwJeRWx7xSuhBRKq48wjcH-MwOg/s1600-h/oxygen-doc-menu.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 107px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGlom4WrMXyHVC55Ve3CjWHTgWqq2KEBXExMDmblmEaZkPCav_E5kEpvfkamuowpCYVHxsilmJKMpWugEuahhXjWsNJNleN81Js1TPmDXdzv8fwJeRWx7xSuhBRKq48wjcH-MwOg/s400/oxygen-doc-menu.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5307450712303785746" /></a>
<p>But having XSLStyle integrated within oXygen would bring several
advantages. It would always be installed alongside with oXygen. I am
a freelance consultant and move a lot between different companies,
using several computers, with different system administration
policies. Thanks to the per-person-license model of oXygen, and its
platform independence, I can take it with me everywhere, and be
quickly productive, without having to install separately a JRE, Saxon,
FOP, Xerces, DocBook environment, RELAX NG tools, Schematron
skeletons, Emacs with nXML and others modes, and even Cygwin to be
able to create shell scripts and Makefile to automate tasks. But I
still have to download XSLStyle separately, open one of its
stylesheets to copy and paste a documentation sample and the correct
namespace bindings. Of course, it would be time saving to have an
XSLStyle framework directly in oXygen.</p>
<p>Besides that point, oXygen could offer editing facilities for
stylesheet components documentation as well. When you want to
document a named template with several parameters, you have to create
the documentation structure as showed above, and create a
<code>doc:param</code> element for each parameter, with the correct
name. This could be automatically done with a specific action, to add
an empty documentation structure to a particular component or even to
each non-documented yet componnents in the stylesheet:</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg80tGLHlkepgN2fVNLvkIhv9n3pcJDLSVjDOXjPctths55movz4sCqO-HvS5cRdKzkqrMpYLoaxv9q8esiUoH6k3PrpiJGobBhx1d1pxJo8_pg7RuWhZPOmnJlnEzknyRU5OGL-g/s1600-h/oxygen-xslstyle-menu.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 249px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg80tGLHlkepgN2fVNLvkIhv9n3pcJDLSVjDOXjPctths55movz4sCqO-HvS5cRdKzkqrMpYLoaxv9q8esiUoH6k3PrpiJGobBhx1d1pxJo8_pg7RuWhZPOmnJlnEzknyRU5OGL-g/s400/oxygen-xslstyle-menu.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5307450818253572962" /></a>
<p>There would not have anymore the need to attach the stylesheet to an
XSLStyle scenario neither. When I work on a stylesheet, I like to
have its current scenario bound regarding what I am working on in
particular. Switching back and forth between this scenario and the
XSLStyle scenario does not really make sense. It would be more
productive to have a <code>Tools > Generate Documentation > XSLT
Documentation...</code> action as for the other file type, in my
humble opinion.</p>
<p>And finally, oXygen would even be able to report some
<em>documentation errors</em> directly in the editor pane, as wrong
names in documenting parameters.</p>
<p>I hope oXygen team will be intersted to add support for XSLStyle, as
this would be convenient, but also would spread XSLT writing best
practices advocated by XSLStyle. Anyway, thanks to the team for
listening to user requests, this is too rarely the case in other
companies, and of course to Ken for XSLStyle.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com2tag:blogger.com,1999:blog-33074681.post-52980942378393190682008-12-09T02:53:00.005+01:002008-12-10T00:22:37.559+01:00FXSL currying and nestable sequences<p>After an <a
href="http://sf.net/forum/forum.php?thread_id=2633995&forum_id=188304">interesting
discussion</a> on the FXSL Help forum, the problem of currying and
nested sequences showed up again. The <a
href="http://fxsl.sf.net/">FXSL project</a> provides, among other
things, first-class citizen functions. Basically, it represents a
function as an element. When executing such a function, the
dispatching to the code is done by applying templates on that element.</p>
<p>An interesting feature of FXSL is the ability to <em>curry</em>
parameters to a function, to create an other function of a lesser
order. The principle is to <em>attach</em> parameters to the
function. This new function can then be used as any other function,
with specified parameters bound to specified values.</p>
<p>The result of currying is then another first-class citizen function.
So it has to be a node, because <code>f:apply()</code> applies
templates on it to find the code to execute. And it has to be a
single item, in order to be used as any other items (in particular its
behaviour in sequence handling and atomization.) The later point
makes it impossible to use a sequence as result of currying.</p>
<p>The approach taken by FXSL for now is to create an XML element as the
result of <code>f:curry()</code>. This element contains several
information: the child <code>fun</code> holds the curried function
(may be itself a currying), <code>cnArgs</code> is the cardinality of
the curried function and then the childs <code>arg</code> hold the
curried values. For instance, the expression <code>f:curry(my:add(),
2, 1024)</code> will return the following element:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">f-curry</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">f-curry</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">f-curry</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fxsl.sf.net/curry</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">fun</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">my</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">add</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">my</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">urn:X-FGeorges.org:tests:curry-sref.xsl</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">fun</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">cnArgs</span><span class="fl-nxml-tag-delimiter">></span><span class="nxml-text">2</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">cnArgs</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">arg</span> <span class="fl-nxml-attribute-local-name">t</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="nxml-text">1024</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">arg</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">f-curry</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">f-curry</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>This approach is convenient because we can use any structure we need
to represent currying. Unfortunately, the semantics of adding items
to an XML tree implies to copy nodes and to make nodes from atomic
values. That means that if the curried argument is an XML element,
piece of a whole document, it will be copied to the element
representing currying. For example if the curried function uses the
ancestor axis on this curried element, it will see the
<code>f-curry:f-curry</code> element, instead of the ancestors in the
original document. That was actually the problem reported by
Christoph Lange on the FXSL forum.</p>
<p>And this leads to other problems related to identity. For
instance, items are transformed to nodes. FXSL resolves that problem
by recording the initial type in the currying structure, and convert
the node back to that type. While this is ok for standard simple
types, that can't be applied to user-defined simple types. Another
example is for validated nodes; they loose their type annotations when
added to the currying structure, which can be a problem for the
curried function. You can find more about this topic in <em><a
href="http://fgeorges.blogspot.com/2006/08/type-preserving-copy-in-xslt-20.html">Type-preserving
copy in XSLT 2.0</a></em>.</p>
<p>Actually, all those problem could be solved with a simple feature
that does not exist in standard XPath: the ability to nest sequence.
If we could nest sequences, or if we had a special type of sequences
that wouldn't atomize when added to another sequence, we could use
them as the result of currying. Even if that's not a node anymore, we
could adapt <code>f:apply()</code> to handle those particular
sequences and use its, say, first item as the node to apply templates
on.</p>
<p>The good news is that this is simple to implement such a sequence
as a Java extension in Saxon. Here is a very simple implementation.
I have called it SRef, for Sequence Reference. I guess we would need
something more elaborated to be efficient and general-purpose, but
this is just a proof-of-concept:</p>
<pre class="drkm-code-div">
<span class="fl-keyword">package</span> org.fgeorges.<span class="fl-constant">saxon</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">util</span>.<span class="fl-type">ArrayList</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">util</span>.<span class="fl-type">List</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">ArrayIterator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">Item</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">SequenceIterator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">XPathException</span>;
<span class="fl-doc">/**
* XPath sequence reference, or non-atomizable XPath sequence.
*
* </span><span class="fl-doc"><span class="fl-constant">@author</span></span><span class="fl-doc"> Florent Georges - fgeorges.org
* </span><span class="fl-doc"><span class="fl-constant">@date</span></span><span class="fl-doc"> 2006-12-01
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">SequenceRef</span>
{
<span class="fl-keyword">public</span> SequenceRef(<span class="fl-type">SequenceIterator</span> <span class="fl-variable-name">seq</span>) <span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
myIter = seq.getAnother();
}
<span class="fl-keyword">public</span> <span class="fl-type">SequenceIterator</span> <span class="fl-function-name">getSequence</span>()
{
<span class="fl-keyword">return</span> myIter;
}
<span class="fl-keyword">static</span> <span class="fl-keyword">public</span> <span class="fl-type">boolean</span> <span class="fl-function-name">isSequenceRef</span>(<span class="fl-type">Object</span> <span class="fl-variable-name">obj</span>)
{
<span class="fl-keyword">return</span> obj <span class="fl-keyword">instanceof</span> SequenceRef;
}
@Override
<span class="fl-keyword">public</span> String toString()
{
<span class="fl-keyword">throw</span> <span class="fl-keyword">new</span> <span class="fl-type">RuntimeException</span>(<span class="fl-string">"toString not supported, cannot be added to a tree!"</span>);
}
<span class="fl-keyword">private</span> <span class="fl-type">SequenceIterator</span> <span class="fl-variable-name">myIter</span> = <span class="fl-constant">null</span>;
}
</pre>
<p>This implementation in Java is coupled to an simple API in XPath.
Three functions are created: <code>sref:make-sref()</code> takes a
sequence and returns an sref for this sequence,
<code>sref:sequence()</code> takes an sref and return the original
sequence, and <code>sref:is-sref()</code> get an item and return true
if it is an sref. The following XSLT module defines those
functions:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-processing-instruction-delimiter"><?</span><span class="fl-nxml-processing-instruction-target">xml</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">encoding</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">UTF-8</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-processing-instruction-delimiter">?></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">sref</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.fgeorges.org/xslt/sref</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">impl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:org.fgeorges.saxon.SequenceRef</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs sref impl</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:make-sref</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">seq</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">impl:new($seq)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:sequence</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ref</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">impl:getSequence($ref)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:is-sref</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:boolean</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ref</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">impl:isSequenceRef($ref)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:atomize</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">seq</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
for $item in $seq return
if ( sref:is-sref($item) ) then
sref:sequence($item)
else
$item</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:deep-atomize</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">seq</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
for $item in $seq return
if ( sref:is-sref($item) ) then
sref:deep-atomize(sref:sequence($item))
else
$item</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>With those simple functions, it is then possible to modify
<code>f:curry()</code> and <code>f:apply()</code> to support (to take
advantage of) SRefs. The folowing is a simple example (supporting
only currying a function of cardinality 2 with a single argument). I
create a first-citizen function <code>my:add()</code> that takes two
integers and returns their sum, I write new versions of
<code>f:apply()</code> and <code>f:curry()</code>, then I call
<code>my:add()</code> both directly and with currying:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-processing-instruction-delimiter"><?</span><span class="fl-nxml-processing-instruction-target">xml</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">encoding</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">UTF-8</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-processing-instruction-delimiter">?></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">f</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fxsl.sf.net/</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">my</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">urn:X-FGeorges.org:tests:curry-sref.xsl</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">sref</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.fgeorges.org/xslt/sref</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">impl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:org.fgeorges.saxon.SequenceRef</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs f my sref impl</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">import</span> <span class="fl-nxml-attribute-local-name">href</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref.xsl</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
The my:add() first class function.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:add</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">element()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">my</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">add</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:add</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">node()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$my:add</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:add</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">lhs</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">rhs</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$lhs + $rhs</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:add</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:FXSL</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg2</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:add($arg1, $arg2)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Apply on SRefs.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:apply-sref</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">pFunc</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">seq</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:sequence($pFunc)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$seq[1]</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:FXSL</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">seq</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$seq</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Currying using SRefs.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:curry-sref</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">f-c-s</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fxsl.sf.net/curry-sref</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">pFun</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">node()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">pNargs</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">curry-fun</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">element()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">f-c-s</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">f-c-s</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
sref:make-sref(($curry-fun, $pFun, $pNargs, sref:make-sref($arg1)))</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f-c-s:*</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:FXSL</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">f-c-s</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://fxsl.sf.net/curry-sref</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">seq</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">item()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$seq[2]</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:FXSL</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">sref:sequence($seq[position() gt 3])</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">arg2</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$arg1</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
The testing template.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">/</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">test-1</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:add(512, 1024)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">test-1</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">test-2</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fun</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:curry-sref(my:add(), 2, 1024)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">f:apply-sref($fun, 512)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">test-2</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Thanks to Christoph Lange for the original problem and to Dimitre for his ideas.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-4665857746381362172008-11-09T22:58:00.006+01:002009-11-12T10:20:46.900+01:00XProc with XSLT completion in oXygen<p><em>[[ Note on 2009-11-12: oXygen 11.0 comes with built-in support
for XProc and Calabash, so you shouldn't need this anymore if you have
oXygen 11+. ]]</em></p>
<p>After having played a little bit with <a href="http://www.w3.org/TR/xproc/">XProc</a>, and having written a few simple XProc definitions with <a href="http://www.oxygenxml.com/">oXygen</a>, I was tired to always check the step names spelling and to use copy & paste intensively. So I decided to add support for the XProc document type in oXygen.</p>
<p>Thanks to the XProc WG, who has published a schema as part of the current WD (and has done so in various schema languages,) the first step was quite straigthforward. Download the two RNC modules from the current WD, in appendix "D Pipeline Language Summary" (direct links: <a href="http://www.w3.org/TR/xproc/schemas/xproc.rnc">xproc.rnc</a> and <a
href="http://www.w3.org/TR/xproc/schemas/steps.rnc">steps.rnc</a>.) While editing an XProc definition, click the <em>Associate Schema...</em> button (see the screenshot below.) In the dialog box, choose <em>RelaxNG Schema</em>, choose the option <em>Compact syntax</em> and select the <em>xproc.rnc</em> file you have just downloaded. The only configuration to change is in <em>Preferences</em> / <em>XML</em> / <em>XML Parser</em> / <em>RELAX NG</em>, and unselect the option <em>Check ID/IDREF</em> (thanks, George.)</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDC7c0wCQsyTsRMrgEogUfBqwhz6TMpL5Rnvv_BejKCHhjX_r8o0XwGlMsno3dyM75gHyP6jf9OYtQ_moaEXcfkgsTK3x8CcWuFkcWYmf9AWV7XeGGNZs9SmBlwmZTfASaPZUXdg/s1600-h/oxygen-associate-schema.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 139px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDC7c0wCQsyTsRMrgEogUfBqwhz6TMpL5Rnvv_BejKCHhjX_r8o0XwGlMsno3dyM75gHyP6jf9OYtQ_moaEXcfkgsTK3x8CcWuFkcWYmf9AWV7XeGGNZs9SmBlwmZTfASaPZUXdg/s320/oxygen-associate-schema.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5266783015086279650" /></a>
<p>Now, you can validate your XProc definition while editing it, as well as enjoy the completion from oXygen. So far, so good. But while editing XProc definitions, you will often use small inline XSLT stylesheets (at least, I do.) And it would be great to have validation and completion for those stylesheet as well. So you have to combine the XProc schemas with XSLT schemas. And thanks to Norman Walsh, there is an RNC schema that validates both XSLT 1.0 and 2.0. You can download them from <a href="http://norman.walsh.name/2006/07/12/xslt20">his blog</a> (direct links: <a
href="http://norman.walsh.name/2006/07/12/examples/xslt.rnc">xslt.rnc</a>, <a
href="http://norman.walsh.name/2006/07/12/examples/xslt10.rnc">xslt10.rnc</a> and <a
href="http://norman.walsh.name/2006/07/12/examples/xslt20.rnc">xslt20.rnc</a>.)</p>
<p>So far, you have then the schemas for XSLT, and the schemas for XProc, without XSLT. So you have to plug the former within the later. Unfortunately, the XProc RNC schema use the same pattern for <tt>p:inline</tt> for all steps (that patterns simply accepts anything.) The simple approach here is to redefine that pattern to accept anything except elements in the XSLT namespace, or to accept the <tt>xsl:stylesheet</tt> element defined in the XSLT schemas. The drawback is that this redefinition occurs for all steps; but so far, it hasn't been a restriction. The custom RNC file is just:</p>
<pre class="drkm-code-div">
<span class="fl-preprocessor">default namespace</span> <span class="fl-function-name">p</span> = <span class="fl-string">"http://www.w3.org/ns/xproc"</span>
<span class="fl-preprocessor">namespace</span> <span class="fl-function-name">xsl</span> = <span class="fl-string">"http://www.w3.org/1999/XSL/Transform"</span>
<span class="fl-keyword">include</span> <span class="fl-string">"xproc.rnc"</span> {
<span class="fl-function-name">Inline</span> =
<span class="fl-keyword">element</span><span class="fl-variable-name"> inline </span>{
exclude-inline-prefixes.attr?,
common.attributes,
( xslt | AnyButXSLT )
<span class="fl-comment"># I am not sure which one is better...
</span> <span class="fl-comment"># ( xslt | AnyButStylesheet )
</span> }
}
<span class="fl-function-name">xslt</span> = <span class="fl-keyword">external</span> <span class="fl-string">"xslt.rnc"</span>
<span class="fl-function-name">AnyButXSLT</span> =
<span class="fl-keyword">element</span><span class="fl-variable-name"> (* - xsl:*) </span>{
(_any.attr | <span class="fl-italic">text</span> | Any)*
}
<span class="fl-function-name">AnyButStylesheet</span> =
<span class="fl-keyword">element</span><span class="fl-variable-name"> (* - (xsl:stylesheet|xsl:transform)) </span>{
(_any.attr | <span class="fl-italic">text</span> | Any)*
}
</pre>
<p>Just copy & paste this code to a file, for instance <tt>xproc-with-xslt.rnc</tt> (take care to adapt the two paths to the other RNC schemas as needed.) Then remove the <tt><?oxygen RNGSchema...?></tt> previously added by oXygen to your XProc definition, and associate now your new RNC grammar. That's all!</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_orFAMIeTFhMnk4kmcb15T1YkRaQvTjdTyhX6rtJ78yFVRF_gwih5oQPly-sFE3eB3BvpUXiA7MSfBFvQyxfBp_GgjgqybTkWqNwJ8__qVm3k8XFMdzASM1B7xhrCjW26EffXoQ/s1600-h/xslt-completion-in-xproc.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 116px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_orFAMIeTFhMnk4kmcb15T1YkRaQvTjdTyhX6rtJ78yFVRF_gwih5oQPly-sFE3eB3BvpUXiA7MSfBFvQyxfBp_GgjgqybTkWqNwJ8__qVm3k8XFMdzASM1B7xhrCjW26EffXoQ/s400/xslt-completion-in-xproc.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5266786907739280818" /></a>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com4tag:blogger.com,1999:blog-33074681.post-52400135862795041782008-10-30T18:58:00.008+01:002009-11-12T10:22:00.769+01:00Poor man's Calabash integration into oXygen<p><em>[[ Note on 2009-11-12: oXygen 11.0 comes with built-in support for
XProc and Calabash, so you don't need this anymore if you have oXygen
11+. ]]</em></p>
<p><a href="http://xmlcalabash.com/">XML Calabash</a>, the <a href="http://xproc.org/">XProc</a> processor from Norman Walsh, becomes more mature from day to day. Here is a very simple (but very limited too) way to integrate it into the great <a href="http://www.oxygenxml.com/">oXygen XML IDE</a>. Well, the word <em>integrate</em> is maybe too much for this simple trick, that will just add a button in the toolbar to execute the currently edited XProc definition file. But at least that will prevent you to switch between your IDE and a console.</p>
<p>You have to register Calabash as an external tool within oXygen. Go to <tt>Tools</tt> > <tt>External Tools</tt> > <tt>Preferences</tt> > <tt>New</tt>, and fill the various fields. The point is to correctly set the working directory to <tt>${cfd}</tt> and the command line to something like:</p>
<pre class="drkm-code-div">
java -cp ".../calabash.jar:.../saxon9.jar:.../saxon9-s9api.jar"
com.xmlcalabash.drivers.Main ${cfne}
</pre>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8jSLBkLDxuLvAiD0DjTVj_i6MSNfvv2F806oBODKm2DA9nz3WkG79ERGR4OiGyxpYWvp3oRQv8AoM9oZwPgW1tZJ78p_qUtXbQwUcyZnOlHPcHSCOrAkv0SjNrdhuzrewGiz31A/s1600-h/oxygen-calabash-exttool.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 251px; height: 320px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8jSLBkLDxuLvAiD0DjTVj_i6MSNfvv2F806oBODKm2DA9nz3WkG79ERGR4OiGyxpYWvp3oRQv8AoM9oZwPgW1tZJ78p_qUtXbQwUcyZnOlHPcHSCOrAkv0SjNrdhuzrewGiz31A/s320/oxygen-calabash-exttool.jpg" alt="" id="BLOGGER_PHOTO_ID_5263009622740534114" border="0" /></a></p>
<p>Of course, you have to set the absolute path to the JAR files on your machine. Be sure to use "<tt>:</tt>" as the path separator on Linux and "<tt>;</tt>" on Windows. You can also set additional options like <tt>-Dcom.xmlcalabash.phonehome.email=your@email.com</tt>. In other words, just use the command line you usually use to launch Calabash.</p>
<p>When this is done, you will have a new button on your toolbar, called Calabash (be sure to have selected the <em>External Tools</em> toolbar.) When your are editing an XProc definition, you can press that button to execute it with Calabash, viewing the output in the result panel.</p>
<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQFXeTk91kwE9umPXVkHQE88RrcI_N57pboT5WicbrWy52mdk2u7GO9hd8LJalIk1biOkchmMTyf922Z09wLXlCEQ7t3YTLRWSJ3h7LFENh7-eVrxH0r-I5RkSV-mQIMUYqukA3Q/s1600-h/oxygen-calabash-button.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 162px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQFXeTk91kwE9umPXVkHQE88RrcI_N57pboT5WicbrWy52mdk2u7GO9hd8LJalIk1biOkchmMTyf922Z09wLXlCEQ7t3YTLRWSJ3h7LFENh7-eVrxH0r-I5RkSV-mQIMUYqukA3Q/s320/oxygen-calabash-button.jpg" alt="" id="BLOGGER_PHOTO_ID_5263009819073173746" border="0" /></a>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com4tag:blogger.com,1999:blog-33074681.post-40688983703517758552008-04-02T02:45:00.003+02:002008-04-02T03:08:25.839+02:00Simple SVG chart generation with XSLT<p>This week, for my job, I have to create a report generator for a
financial company. The reports must be in PDF, so I naturally decided
to use XSL-FO. Among other things, the reports contain graphical
charts with, you know, financial stuff. The client wants its
developers to be able to generate JPEG files themselves, so for the
charts I just have to include external graphic files.</p>
<p>But I was curious to see if SVG was adapted to fit in this
scenario. So this evening, after my working hours, I created a sample
input files and started to learn a little bit about SVG. It was
incredible as I was able to quickly get the result I wanted for a
static SVG document.</p>
<p>Then the fun part started: create the XSLT stylesheet to transform
the input document to the final SVG chart. The goal is of course to
have a simple stylesheet that is generic enough to not be bound to
specific lengths or other magic values.</p>
<p>And I think the result is quite interesting, assuming it was
written in a few hours, without knowledge of SVG at the beginning. Of
course the kind of chart is fixed, as well the input format is fixed.
But it is flexible enough to adapt to various lengths, various Y axis
scales, and such.</p>
<p>This stylesheet is not at all aimed to be used as such, but I think
it can be a good strating point for similar SVG charts generation with
XSLT. If I have the time, and if I want to, I'd try to make it more
configurable, especially in the way the input is provided (I think
FXSL can be of great help here to provide adapters for any input
document type.)</p>
<p>Basically the input looks like the following. Those numbers are
the number of post to XSL List by month, for 2007 (stolen from
MarkMail.org):</p>
<pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">input</span> <span class="fl-nxml-attribute-local-name">min-value</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">500</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">step-value</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">100</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">step-number</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">5</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">784</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Jan-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">765</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Feb-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">910</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Mar-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">734</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Apr-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">907</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">May-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">626</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Jun-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">865</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Jul-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">682</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Aug-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">790</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Sep-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">725</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Oct-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">649</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Nov-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">val</span> <span class="fl-nxml-attribute-local-name">v</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">577</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Dec-07</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">val</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">input</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>The result of the transformation looks like this (screenshot
of the Firefox rendering of the SVG document):</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKyJe7afilr5d7my8iIFHfJGnFi6iTAubCXD9RRewUrbVcbeYNC1PYTff8QfVrjt5aORNAYVjnVp2ddFztRoSfAuPNXkNZHABoLXopXFEtX1aeMbv70qU7AzYkDcNuoJUG4HQpjg/s1600-h/svg-chart.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKyJe7afilr5d7my8iIFHfJGnFi6iTAubCXD9RRewUrbVcbeYNC1PYTff8QfVrjt5aORNAYVjnVp2ddFztRoSfAuPNXkNZHABoLXopXFEtX1aeMbv70qU7AzYkDcNuoJUG4HQpjg/s640/svg-chart.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5184444488776611426" /></a></p>
<p>And finally here is the stylesheet itself:</p>
<pre class="drkm-code-div"><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">svg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2000/svg</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">my</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.fgeorges.org/TMP/svg/charts#internals</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
+- - - - - - - - - - - - - - - - - - - - - - - -+
| +- - - - - - - - - - - - - - - - - - - -+ nn |
| | | |
| | o | |
| | . . . . . . . . . . .o. . . . . oo. . | nn |
| | oo oo oo | |
| | o oo o oo | |
| | . . . oo oo . ooo . . . .ooo. . . . . | nn |
| | ooo ooo | |
| | o | |
| +- -|- -|- -|- -|- -|- -|- -|- -|- -|- -+ nn |
| x x x x x x x x x |
+- - - - - - - - - - - - - - - - - - - - - - - -+
The outer box is the whole space that the diagram will occupy.
The length between that imaginary box and the top-left corner
of the diagram is represented by '$init-x' and '$init-y'.
The length of the rectangle of the diagram itself (the inner
box in the picture) is represented by '$width' and '$height'.
The number of steps on the right-hand Y axis (in the picture
there are 3 steps, that is 3 steps "between" the various "nn"s)
is represented by @step-number in the input document. The
numeric value between two steps is @step-value.
The diagram's plot (the "o"s) and the X axis (the "x"s) are
represented by the input document. Exemple of input:
<input min-value="100" step-value="5" step-number="5">
<val v="110">Jan-08</val>
<val v="107">Feb-08</val>
<val v="123">Mar-08</val>
</input>
In this example, the Y axis will be from 100 to 125, with a
line (and a label) from 5 to 5. The X axis will have 3 labels
(from Jan to Mar) and the plot will be computed from 3 values:
110, 107 and finally 123.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">init-x</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">10</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">init-y</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">10</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">width</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">500</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">height</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">250</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">baseline</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$height + $init-y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
For test purpose: an root SVG element that should be ok for the
default values of the global parameters, provided an input of
10 or 20 values.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">/</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">svg</span> <span class="fl-nxml-attribute-local-name">width</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">540</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">height</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">300</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">g</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">g</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">svg</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
The Y axis, the X axis and the plot line.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">input</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> the diagram's box </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">rect</span> <span class="fl-nxml-attribute-local-name">x</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $init-x }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">y</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $init-y }</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">width</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $width }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">height</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $height }</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">fill</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">#fff</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">stroke</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">#000</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> the Y axis's labels and their lines </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:lines(@min-value, @step-value, @step-number)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$width div count(*)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> the X axis's labels </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$len</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> the plot line </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">path</span> <span class="fl-nxml-attribute-local-name">stroke</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">blue</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">stroke-width</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">fill</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">none</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">attribute</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">d</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">*</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">path</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$len</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">min</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">@min-value</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">with-param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">one-y-len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
( $height div @step-number ) div @step-value</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">attribute</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">path</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Draw a label on the X axis.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">val</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">x</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:x-pos($len, position())</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">path</span> <span class="fl-nxml-attribute-local-name">d</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">M { $x },{ $baseline } L { $x },{ $baseline + 5 }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">stroke</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">#000</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span> <span class="fl-nxml-attribute-local-name">x</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $x + 10 }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">y</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $baseline + 15 }</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">transform</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">rotate(-45 { $x + 10 } { $baseline + 15 })</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">font-size</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">10px</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">text-anchor</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">end</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">.</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Compute one single step of an SVG path's @d, to draw the plot.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">val</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">path</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">min</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">one-y-len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">if ( position() eq 1 ) then 'M' else 'L'</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span> <span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:x-pos($len, position())</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">,</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:y-pos($one-y-len, @v, $min)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span> <span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
The lines for each Y step, as well as the label for each Y
step.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:lines</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">element()+</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">min</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">step-val</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">step-num</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">step-len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$height div $step-num</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> the N - 1 lines </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1 to ($step-num - 1)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">(. * $step-len) + $init-y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">path</span> <span class="fl-nxml-attribute-local-name">d</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">M { $init-x },{ $y } L { $width + $init-x },{ $y }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">stroke</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">#AAA</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> the N + 1 labels </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">0 to $step-num</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">(. * $step-len) + $init-y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span> <span class="fl-nxml-attribute-local-name">x</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $width + $init-x + 25 }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">y</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $y + 4 }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">font-size</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">10px</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">text-align</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">end</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">text-anchor</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">end</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">font-family</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Helvetica Condensed</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$min + ($step-num - .) * $step-val</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">svg</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Compute the absolute X position from the ordinal position and
the length of one X step.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:x-pos</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">step-len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">position</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">($step-len * $position) - ($step-len div 2) + $init-x</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Compute the absolute Y position for one point of the diagram's
plot. $one-len is the length of 1 on the Y axis, $value is the
Y value of the plot's point, and $min is the minimal value on
the Y axis.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:y-pos</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">one-len</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">value</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">min</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:double</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">mid</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$height div 2</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> scale the value to the scale [min - max] </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">val</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">($value - $min) * $one-len</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> reverse 0->$height and $height->0, 'cause in SVG y=0 is at top </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">rev</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">(- ($val - $mid)) + $mid</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> slide because our graph begins at y=$init-y </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$rev + $init-y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com9tag:blogger.com,1999:blog-33074681.post-32205393599795389672008-03-31T05:16:00.002+02:002008-04-07T05:37:00.069+02:00HTTP extension for Saxon<p>I have just finished a little extension function for Saxon, to be
able to send HTTP request from XSLT 2.0 (and get the result back).
The idea is based on the SOAP extension from Andrew Welch, but is less
restricted, as it can perform other HTTP requests (besides SOAP
request over HTTP.)</p>
<p>The function take two parameters: a URI and an element that describe
the request (the payload, the headers, the HTTP method, etc.) The later
looks like:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">http-request</span> <span class="fl-nxml-attribute-local-name">method</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">post</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mime-type</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">text/xml</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">charset</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">utf-8</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">header</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Header-Name</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">...</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">header</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">header</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Header2-Name</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">...</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">header</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">body</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">
The textual value of body will be the payload of the HTTP request...
</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">body</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">http-request</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Let's say such an element is bound to the variable $request, then
you can call <code>ex:http-send($request, 'http://...')</code>, and
you will get a result that will look like:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">http-response</span> <span class="fl-nxml-attribute-local-name">code</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">200</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">message</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">OK</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">message</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">header</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Header-Name</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">...</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">header</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">header</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Header-x-Name</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">...</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">header</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">body</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">
The textual value of body was the payload of the HTTP response...
</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">body</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">http-response</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>All the info, javadoc, JAR file, sample, can be found at <a
href="http://www.fgeorges.org/xslt/saxon-ext/">http://www.fgeorges.org/xslt/saxon-ext/</a>.
This page contains a full sample sending a SOAP message to a Web
service and formating the result to a simple text.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com4tag:blogger.com,1999:blog-33074681.post-46076144811144289482008-01-10T21:16:00.000+01:002008-01-11T10:19:00.719+01:00Emacs: favourite directories implementation<p>Today, I have finally taken a look at one of the simple
features I always missed in Emacs: the ability to define a
set of "favourite directories." That is, a set of named
directories that one can use in the minibuffer when prompted
for instance to open a file. Given a set of such dirs:</p>
<pre class="drkm-code-div">
emacs-src -> /enter/your/path/to/emacs/sources
projects -> /path/to/some/company/projects
now -> @projects/the/project/I/am/working/on
</pre>
<p>one can use the following path in the minibuffer to open a
file, for instance using C-x C-f:</p>
<pre class="drkm-code-div">
@emacs-src/lisp/files.el
@emacs-src/src/alloc.c
@projects/great/README
@now/src/some/stuff.txt
</pre>
<p>Doing so, completion is available for both directory names
and files under their target directories. For instance, to
open the third file above, you only have to type:</p>
<pre class="drkm-code-div">
C-x C-f @ p <tab> g <tab> R <tab> <enter>
</pre>
<p>The implementation I have just written is really simple, but
useful yet. It implements all described above (including
recursive defined directories, as the '@now' above.) Thanks
to Emacs, I am still suprised by the facility to implement
such a feature!</p>
<p>The code was written on GNU Emacs 22.1 on Windows, but
should work on any platform, and I think on Emacs 21 as
well.</p>
<pre class="drkm-code-div">
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">TODO: Make a custom variable.
</span>(<span class="fl-keyword">defvar</span> <span class="fl-variable-name">drkm-fav:favourite-directories-alist</span>
'((<span class="fl-string">"saxon-src"</span> . <span class="fl-string">"y:/Saxon/saxon-resources9-0-0-1/source/net/sf/saxon"</span>)
(<span class="fl-string">"kernow-src"</span> . <span class="fl-string">"~/xslt/kernow/svn-2007-09-29/kernow/trunk/src/net/sf/kernow"</span>))
<span class="fl-doc">"See `</span><span class="fl-doc"><span class="fl-constant">drkm-fav:handler</span></span><span class="fl-doc">'."</span>)
(<span class="fl-keyword">defvar</span> <span class="fl-variable-name">drkm-fav::fav-dirs-re</span>
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">TODO: Is tehre really no other way (than mapcar) to get the list
</span> <span class="fl-comment-delimiter">;; </span><span class="fl-comment">of the keys of an alist?!?
</span> (concat
<span class="fl-string">"^@"</span>
(regexp-opt
(mapcar 'car drkm-fav:favourite-directories-alist)
t))
<span class="fl-doc">"Internal variable that stores a regex computed from
`</span><span class="fl-doc"><span class="fl-constant">drkm-fav:favourite-directories-alist</span></span><span class="fl-doc">'. WARNING: This is not
updated automatically if the later variable is changed."</span>)
(<span class="fl-keyword">defun</span> <span class="fl-function-name">drkm-fav:handler</span> (primitive <span class="fl-type">&rest</span> args)
<span class="fl-doc">"Magic handler for favourite directories.
With this handler installed into `</span><span class="fl-doc"><span class="fl-constant">file-name-handler-alist</span></span><span class="fl-doc">', it is
possible to use shortcuts for often used directories. It uses
the mapping in the alist `</span><span class="fl-doc"><span class="fl-constant">drkm-fav:favourite-directories-alist</span></span><span class="fl-doc">'.
Once installed, say you have the following alist in the mapping
variable:
((\"dir-1\" . \"~/some/real/dir\")
(\"dir-2\" . \"c:/other/dir/for/windows/users\"))
You can now use \"@dir-1\" while opening a file with C-x C-f for
instance, with completion for the abbreviation names themselves
as well as for files under the target directory."</span>
(<span class="fl-keyword">cond</span>
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">expand-file-name
</span> ((and (eq primitive 'expand-file-name)
(string-match drkm-fav::fav-dirs-re (car args)))
(replace-match
(cdr (assoc (match-string 1 (car args))
drkm-fav:favourite-directories-alist))
t t (car args)))
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">file-name-completion
</span> ((and (eq primitive 'file-name-completion)
(string-match <span class="fl-string">"^@</span><span class="fl-string"><span class="fl-regexp-grouping-backslash">\\</span></span><span class="fl-string"><span class="fl-regexp-grouping-construct">(</span></span><span class="fl-string">[</span><span class="fl-string"><span class="fl-negation-char">^</span></span><span class="fl-string">/]*</span><span class="fl-string"><span class="fl-regexp-grouping-backslash">\\</span></span><span class="fl-string"><span class="fl-regexp-grouping-construct">)</span></span><span class="fl-string">$"</span> (car args)))
(<span class="fl-keyword">let</span> ((compl (try-completion
(match-string 1 (car args))
drkm-fav:favourite-directories-alist)))
(<span class="fl-keyword">cond</span> ((eq t compl)
(concat <span class="fl-string">"@"</span> (match-string 1 (car args)) <span class="fl-string">"/"</span>))
((not compl)
nil)
(t
(concat <span class="fl-string">"@"</span> compl)))))
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">file-name-all-completions
</span> ((and (eq primitive 'file-name-all-completions)
(string-match <span class="fl-string">"^@</span><span class="fl-string"><span class="fl-regexp-grouping-backslash">\\</span></span><span class="fl-string"><span class="fl-regexp-grouping-construct">(</span></span><span class="fl-string">[</span><span class="fl-string"><span class="fl-negation-char">^</span></span><span class="fl-string">/]*</span><span class="fl-string"><span class="fl-regexp-grouping-backslash">\\</span></span><span class="fl-string"><span class="fl-regexp-grouping-construct">)</span></span><span class="fl-string">$"</span> (car args)))
(all-completions
(match-string 1 (car args))
drkm-fav:favourite-directories-alist))
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">Handle any primitive we don't know about (from the info node
</span> <span class="fl-comment-delimiter">;; </span><span class="fl-comment">(info "(elisp)Magic File Names")).
</span> (t (<span class="fl-keyword">let</span> ((inhibit-file-name-handlers
(cons 'drkm-fav:handler
(and (eq inhibit-file-name-operation primitive)
inhibit-file-name-handlers)))
(inhibit-file-name-operation primitive))
(apply primitive args)))))
<span class="fl-comment-delimiter">;; </span><span class="fl-comment">Actually plug the feature into Emacs.
</span>(push '(<span class="fl-string">"\\`@"</span> . drkm-fav:handler) file-name-handler-alist)
</pre>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com3tag:blogger.com,1999:blog-33074681.post-76026320853313646332007-11-03T19:41:00.000+01:002008-01-10T21:13:13.384+01:00XSLT stacktrace with Saxon 9<p>I have played a little bit with the Saxon B's XSLT stack representation.
When an error appears while evaluating a stylesheet, you can indeed
catch the Java exception, so the Java stacktrace, but what is really
interresting is the <em>XSLT stacktrace</em>. That is, where in the
XSLT processing the error occured. For instance "<em>in the function
X, called from the template Y, applied from the external
application</em>".</p>
<p>I didn't find a comprehensive documentation on that subject, so I
experimented a bit with what I got: an <code>XPathException</code> and
from there an <code>XPathContext</code>. Please note I used for that
the new version 9.0.0.1 (I know there are a few differences between
version 8 and 9 in the area of interest here, but I didn't look for
cataloging them).</p>
<p>Let me first introduce a concrete sample. Here is a example of
XSLT stylesheet that will throw an error when applied to itself (there
is a few boilerplate code to avoid to much optimization from
Saxon):</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">fg</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.fgeorges.org/xslt/samples</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">/</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">html</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">head</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">body</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">*</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">body</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">html</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">*</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">nana</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">b</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">name(.)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg:fun(*)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">b</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xsl:function/xsl:choose | aa//bb</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">b</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg:fun(*)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">b</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg:fun</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">n</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">node()*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$n[0][name() = 'inexistent']</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
$n[position() mod 2 eq 0]</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">apply-templates</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$n</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">match</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xsl:otherwise</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">mode</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">y</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">if</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">@test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">'</span><span class="fl-nxml-char-ref-delimiter">&#</span><span class="fl-nxml-char-ref-number">10</span><span class="fl-nxml-char-ref-delimiter">;</span><span class="fl-nxml-attribute-value">'</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">if</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">dummy</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">
error(xs:QName('fg:ERR007'), 'My error message')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">dummy</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>When applied to itself, the stylesheet should throw an error in the
last template rule, matching <code>xsl:otherwise</code>. Here is what
I expect the XSLT stacktrace should look like:</p>
<pre class="drkm-code-div">
ERR007: My error message
in template #y matching "xsl:otherwise" (at style.xsl:47)
`-> /xsl:stylesheet[1]/xsl:function[1]/xsl:choose[1]/xsl:otherwise[1]
applied in function fg:fun #1 (at style.xsl:36)
called in template #y matching "xsl:function/xsl:choose | aa//bb" (at style.xsl:24)
`-> /xsl:stylesheet[1]/xsl:function[1]/xsl:choose[1]
applied in function fg:fun #1 (at style.xsl:36)
called in template nana #y matching "*" (at style.xsl:18)
`-> /xsl:stylesheet[1]/xsl:function[1]
applied in function fg:fun #1 (at style.xsl:36)
called in template nana #y matching "*" (at style.xsl:18)
`-> /xsl:stylesheet[1]
applied in template matching "/" (at style.xsl:10)
`-> /
applied from external application
</pre>
<p>We can see first the message of the error and its local part name.
Then the stack itself is composed by templates and function
calling/applying each other. For a function, there is its name and
its arity: <code>function fg:fun #1</code>. For a template (both
named templates and template rules), there is its name if any, then
its mode if any, and finally its pattern if any (what it is matching):
<code>template nana #y matching "*"</code>. In addition, there is the
location within the stylesheet (the stylesheet module's file name and
the line number) as well as path to the current node within its
document, if any.</p>
<p>This is what I actually get now, except for the pattern. The
initial text of the pattern is not always keep in memory by Saxon. It
is sometimes reconstructed from its internal form (its
<em>compiled</em> form). I'm sure I could improve this situation, but
I didn't yet. In the above example, the only difference is that the
pattern for the first template is not: <code>template #y matching
"xsl:otherwise"</code> but instead: <code>template #y matching
"element({http://www.w3.org/1999/XSL/Transform}otherwise,
xs:anyType)"</code>.</p>
<p>Instead of directly writing those info as I walk the Saxon's stack,
I instead build an alternative Java representation of the XSLt stack,
and I then output it to the console. That way it would be easier to
reuse that code for other purpose (for instance build a graphical view
of the stack within a GUI for Saxon ;-)).</p>
<p>You can find the Java source files there:</p>
<dl>
<dt><a href="http://www.fgeorges.org/purl/20071104/saxon9-xslt-stacktrace.zip">saxon9-xslt-stacktrace.zip</a></dt>
<dd>The ZIP archive with all the files</dd>
<dt><a href="http://www.fgeorges.org/purl/20071104/StackFrame.java">StackFrame.java</a></dt>
<dd>This class represent an abstract XSLT stack frame.</dd>
<dt><a href="http://www.fgeorges.org/purl/20071104/FunctionFrame.java">FunctionFrame.java</a></dt>
<dd>This class represent an XSLT stack frame for a function.</dd>
<dt><a href="http://www.fgeorges.org/purl/20071104/TemplateFrame.java">TemplateFrame.java</a></dt>
<dd>This class represent an XSLT stack frame for a template.</dd>
<dt><a href="http://www.fgeorges.org/purl/20071104/StackVisitor.java">StackVisitor.java</a></dt>
<dd>The stack visitor interface.</dd>
<dt><a href="http://www.fgeorges.org/purl/20071104/Main.java">Main.java</a></dt>
<dd>A sample program that run a transform that throws an error, and
display the obtained XSLT stack.</dd>
<dt><a href="http://www.fgeorges.org/purl/20071104/style.xsl">style.xsl</a></dt>
<dd>The sample transform.</dd>
</dl>
<p>Below are the complete sources inline, for completeness.</p>
<h3>StackFrame.java</h3>
<pre class="drkm-code-div">
<span class="fl-comment-delimiter">/*</span><span class="fl-comment">
* StackFrame.java
*
* Created on Oct 27, 2007, 2:57:04 PM
*/</span>
<span class="fl-keyword">package</span> saxon.xslt.<span class="fl-constant">stacktrace</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-type">XMLConstants</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">namespace</span>.<span class="fl-type">QName</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">SourceLocator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">XPathContext</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">instruct</span>.<span class="fl-type">Template</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">instruct</span>.<span class="fl-type">UserFunction</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">Axis</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">AxisIterator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">Item</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">NodeInfo</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">SequenceIterator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">StandardNames</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">StructuredQName</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">pattern</span>.<span class="fl-type">NameTest</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">pattern</span>.<span class="fl-type">NodeKindTest</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">pattern</span>.<span class="fl-type">NodeTest</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">pattern</span>.<span class="fl-type">NodeTestPattern</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">pattern</span>.<span class="fl-type">Pattern</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trace</span>.<span class="fl-type">InstructionInfo</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trace</span>.<span class="fl-type">Location</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">Mode</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">Rule</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">XPathException</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">type</span>.<span class="fl-type">Type</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">sax</span>.<span class="fl-type">Locator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">sax</span>.<span class="fl-constant">helpers</span>.<span class="fl-type">LocatorImpl</span>;
<span class="fl-doc">/**
* The base class for XSLT stack frames.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">The main entry point are </span><span class="fl-doc"><span class="fl-constant">{@link #makeStack(XPathContext,Locator)}</span></span><span class="fl-doc"> and
* </span><span class="fl-doc"><span class="fl-constant">{@link #makeStack(XPathException)}</span></span><span class="fl-doc">.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant">@author</span></span><span class="fl-doc"> Florent Georges
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">abstract</span> <span class="fl-keyword">class</span> <span class="fl-type">StackFrame</span>
{
<span class="fl-doc">/**
* Get the locator of the XSLT istruction this frame stands for.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">Locator</span> <span class="fl-function-name">getLocator</span>()
{
<span class="fl-keyword">return</span> myLocator;
}
<span class="fl-doc">/**
* Get the path of the current node if any. May be null.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">String</span> <span class="fl-function-name">getPath</span>()
{
<span class="fl-keyword">return</span> myPath;
}
<span class="fl-doc">/**
* Get the next frame in the stack (that is, the frame that </span><span class="fl-doc"><span class="fl-constant"><em></span></span><span class="fl-doc">called</span><span class="fl-doc"><span class="fl-constant"></em></span></span><span class="fl-doc"> this one).
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">StackFrame</span> <span class="fl-function-name">getNext</span>()
{
<span class="fl-keyword">return</span> myNext;
}
<span class="fl-doc">/**
* Set the next frame in the stack (that is, the frame that </span><span class="fl-doc"><span class="fl-constant"><em></span></span><span class="fl-doc">called</span><span class="fl-doc"><span class="fl-constant"></em></span></span><span class="fl-doc"> this one).
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">setNext</span>(<span class="fl-type">StackFrame</span> <span class="fl-variable-name">next</span>)
{
myNext = next;
}
<span class="fl-doc">/**
* Accept a visitor.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">The visitor will visit this frame, then the rest of the stack (the next
* frame, then its next frame, etcetera).</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">abstract</span> <span class="fl-type">void</span> <span class="fl-function-name">acceptVisitor</span>(<span class="fl-type">StackVisitor</span> <span class="fl-variable-name">visitor</span>);
<span class="fl-doc">/**
* Make a stack representation from the XPath exception.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">Just extract the locator from the exception, then call
* </span><span class="fl-doc"><span class="fl-constant">{@link #makeStack(XPathContext,Locator)}</span></span><span class="fl-doc">.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">static</span> <span class="fl-type">StackFrame</span> <span class="fl-function-name">makeStack</span>(<span class="fl-type">XPathException</span> <span class="fl-variable-name">ex</span>)
{
<span class="fl-type">Locator</span> <span class="fl-variable-name">locator</span> = jaxpToSaxLocator(ex.getLocator());
<span class="fl-type">XPathContext</span> <span class="fl-variable-name">ctxt</span> = ex.getXPathContext();
<span class="fl-keyword">return</span> makeStack(ctxt, locator);
}
<span class="fl-doc">/**
* Make a stack representation from the XPath context.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc"><span class="fl-constant"><b></span></span><span class="fl-doc">Discussion</span><span class="fl-doc"><span class="fl-constant"></b></span></span><span class="fl-doc">: The Saxon's XPath context </span><span class="fl-doc"><span class="fl-constant"><em></span></span><span class="fl-doc">seems</span><span class="fl-doc"><span class="fl-constant"></em></span></span><span class="fl-doc"> to be
* organised as following. One context represent either a template, a
* call-template, an apply-template or a function call (and a few other
* like for-each, not relevant here and ignored). On the one hand, that's
* important for a template to have all those things in the contexts, because
* a same template can be called or applied, and a same apply-template can
* apply different template rules. For a function, on the other hand, a
* call identify clearly the function.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">So you have to different types of context to identify the template or
* function you are in: template and function call (as there is no function
* context). And you have three different way of knowing where you are in
* a template or function (where you leave it to another template or
* function, the line number that interests you): apply-templates,
* call-template and function call. The later are encountered first, the
* former later.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">The locaction of the error (the starting point) is again something
* different, that the </span><span class="fl-doc"><span class="fl-constant">{@link TransformerException}</span></span><span class="fl-doc"> will give you.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">So the idea is the following. We know the location to put in the
* stack one (or more) context before the context telling the template or
* function name, mode, arity, etc. The function call does both things:
* it tells the next context the line number to use, and it tell which
* function to use with the current line number.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">So we start by providing the locator, then recurse the contexts. If
* the context is a template, we make a new template frame with the locator,
* then recurse with a null locator. If the context is an apply-templates
* or a call-template, we recurse with the locator the give us. If the
* context is a function call, both things are done: we use the current
* locator to create a new function frame with the function we have, then
* we recurse with the locator the function call gives us.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">Locators are copied to not keep references to a lot of Saxon objects,
* directly or indirectly.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">static</span> <span class="fl-type">StackFrame</span> <span class="fl-function-name">makeStack</span>(<span class="fl-type">XPathContext</span> <span class="fl-variable-name">ctxt</span>, <span class="fl-type">Locator</span> <span class="fl-variable-name">locator</span>)
{
<span class="fl-keyword">return</span> makeStack(ctxt, locator, null);
}
<span class="fl-doc">/**
* Implementation of </span><span class="fl-doc"><span class="fl-constant">{@link #makeStack(XPathContext ctxt, Locator locator)}</span></span><span class="fl-doc">.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">To deal with template frames, we need to keep a reference to the
* </span><span class="fl-doc"><span class="fl-constant"><em></span></span><span class="fl-doc">called</span><span class="fl-doc"><span class="fl-constant"></em></span></span><span class="fl-doc"> frame. Thus this method with an extra parameter.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">StackFrame</span> <span class="fl-function-name">makeStack</span>(<span class="fl-type">XPathContext</span> <span class="fl-variable-name">ctxt</span>, <span class="fl-type">Locator</span> <span class="fl-variable-name">locator</span>, <span class="fl-type">StackFrame</span> <span class="fl-variable-name">called</span>)
{
<span class="fl-comment-delimiter">// </span><span class="fl-comment">stop recursion
</span> <span class="fl-keyword">if</span> ( ctxt == null ) {
<span class="fl-keyword">return</span> null;
}
<span class="fl-type">InstructionInfo</span> <span class="fl-variable-name">info</span> = ctxt.getOrigin().getInstructionInfo();
<span class="fl-keyword">switch</span> ( info.getConstructType() ) {
<span class="fl-keyword">case</span> <span class="fl-constant">StandardNames</span>.XSL_TEMPLATE: {
<span class="fl-comment-delimiter">// </span><span class="fl-comment">path
</span> <span class="fl-type">String</span> <span class="fl-variable-name">path</span> = makePathToCurrentNode(ctxt);
<span class="fl-comment-delimiter">// </span><span class="fl-comment">pattern
</span> <span class="fl-type">Rule</span> <span class="fl-variable-name">rule</span> = ctxt.getCurrentTemplateRule();
<span class="fl-type">String</span> <span class="fl-variable-name">pattern</span> = getPatternText(rule.getPattern());
<span class="fl-comment-delimiter">// </span><span class="fl-comment">name
</span> <span class="fl-type">Template</span> <span class="fl-variable-name">t</span> = (<span class="fl-type">Template</span>) rule.getAction();
<span class="fl-type">QName</span> <span class="fl-variable-name">name</span> = structuredToQName(t.getTemplateName());
<span class="fl-comment-delimiter">// </span><span class="fl-comment">frame & recurse
</span> <span class="fl-type">StackFrame</span> <span class="fl-variable-name">frame</span> = <span class="fl-keyword">new</span> <span class="fl-type">TemplateFrame</span>(path, pattern, name, null, locator);
frame.setNext(makeStack(ctxt.getCaller(), null, frame));
<span class="fl-keyword">return</span> frame;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Location</span>.FUNCTION_CALL: {
<span class="fl-comment-delimiter">// </span><span class="fl-comment">path
</span> <span class="fl-type">String</span> <span class="fl-variable-name">path</span> = makePathToCurrentNode(ctxt);
<span class="fl-comment-delimiter">// </span><span class="fl-comment">name
</span> <span class="fl-type">QName</span> <span class="fl-variable-name">name</span> = structuredToQName(info.getObjectName(ctxt.getNamePool()));
<span class="fl-comment-delimiter">// </span><span class="fl-comment">arity
</span> <span class="fl-type">UserFunction</span> <span class="fl-variable-name">fun</span> = (<span class="fl-type">UserFunction</span>) info.getProperty(<span class="fl-string">"target"</span>);
<span class="fl-type">int</span> <span class="fl-variable-name">arity</span> = fun.getNumberOfArguments();
<span class="fl-comment-delimiter">// </span><span class="fl-comment">frame & recurse
</span> <span class="fl-type">StackFrame</span> <span class="fl-variable-name">frame</span> = <span class="fl-keyword">new</span> <span class="fl-type">FunctionFrame</span>(path, name, arity, locator);
frame.setNext(makeStack(ctxt.getCaller(), <span class="fl-keyword">new</span> <span class="fl-type">LocatorImpl</span>(info), frame));
<span class="fl-keyword">return</span> frame;
}
<span class="fl-keyword">case</span> <span class="fl-constant">StandardNames</span>.XSL_CALL_TEMPLATE: {
<span class="fl-comment-delimiter">// </span><span class="fl-comment">Should always be, but is not...?
</span> <span class="fl-keyword">if</span> ( called <span class="fl-keyword">instanceof</span> TemplateFrame ) {
<span class="fl-type">TemplateFrame</span> <span class="fl-variable-name">frame</span> = (<span class="fl-type">TemplateFrame</span>) called;
frame.setCalled(true);
}
<span class="fl-keyword">return</span> makeStack(ctxt.getCaller(), <span class="fl-keyword">new</span> <span class="fl-type">LocatorImpl</span>(info), called);
}
<span class="fl-keyword">case</span> <span class="fl-constant">StandardNames</span>.XSL_APPLY_TEMPLATES: {
<span class="fl-comment-delimiter">// </span><span class="fl-comment">Should always be, but is not...?
</span> <span class="fl-keyword">if</span> ( called <span class="fl-keyword">instanceof</span> TemplateFrame ) {
<span class="fl-type">TemplateFrame</span> <span class="fl-variable-name">frame</span> = (<span class="fl-type">TemplateFrame</span>) called;
<span class="fl-comment-delimiter">// </span><span class="fl-comment">mode
</span> <span class="fl-type">Object</span> <span class="fl-variable-name">pmode</span> = info.getProperty(<span class="fl-string">"mode"</span>);
<span class="fl-keyword">if</span> ( pmode != null ) {
<span class="fl-type">StructuredQName</span> <span class="fl-variable-name">smode</span> = ((<span class="fl-type">Mode</span>) pmode).getModeName();
frame.setMode(structuredToQName(smode));
}
}
<span class="fl-comment-delimiter">// </span><span class="fl-comment">recurse with a new locator
</span> <span class="fl-keyword">return</span> makeStack(ctxt.getCaller(), <span class="fl-keyword">new</span> <span class="fl-type">LocatorImpl</span>(info), called);
}
<span class="fl-keyword">default</span>: {
<span class="fl-comment-delimiter">// </span><span class="fl-comment">just recurse the next context
</span> <span class="fl-keyword">return</span> makeStack(ctxt.getCaller(), locator, called);
}
}
}
<span class="fl-doc">/**
* Internal helper, returning a representation of a QName for human readers.
*/</span>
<span class="fl-keyword">protected</span> <span class="fl-keyword">static</span> <span class="fl-type">String</span> <span class="fl-function-name">displayQName</span>(<span class="fl-type">QName</span> <span class="fl-variable-name">name</span>)
{
<span class="fl-keyword">if</span> ( <span class="fl-constant">XMLConstants</span>.DEFAULT_NS_PREFIX.equals(name.getPrefix()) ) {
<span class="fl-keyword">return</span> name.getLocalPart();
}
<span class="fl-keyword">else</span> {
<span class="fl-keyword">return</span> name.getPrefix() + <span class="fl-string">":"</span> + name.getLocalPart();
}
}
<span class="fl-doc">/**
* Return the text view of a </span><span class="fl-doc"><span class="fl-constant"><em></span></span><span class="fl-doc">compiled</span><span class="fl-doc"><span class="fl-constant"></em></span></span><span class="fl-doc"> pattern.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">Could be improved to be more human-friendly in some cases.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">String</span> <span class="fl-function-name">getPatternText</span>(<span class="fl-type">Pattern</span> <span class="fl-variable-name">pattern</span>)
{
<span class="fl-type">NodeTest</span> <span class="fl-variable-name">test</span> = pattern.getNodeTest();
<span class="fl-keyword">if</span> ( pattern <span class="fl-keyword">instanceof</span> NodeTestPattern && test <span class="fl-keyword">instanceof</span> NodeKindTest ) {
<span class="fl-keyword">if</span> ( test == <span class="fl-constant">NodeKindTest</span>.ATTRIBUTE ) {
<span class="fl-keyword">return</span> <span class="fl-string">"@*"</span>;
}
<span class="fl-keyword">else</span> <span class="fl-keyword">if</span> ( test == <span class="fl-constant">NodeKindTest</span>.DOCUMENT ) {
<span class="fl-keyword">return</span> <span class="fl-string">"/"</span>;
}
<span class="fl-keyword">else</span> <span class="fl-keyword">if</span> ( test == <span class="fl-constant">NodeKindTest</span>.ELEMENT ) {
<span class="fl-keyword">return</span> <span class="fl-string">"*"</span>;
}
}
<span class="fl-keyword">return</span> pattern.toString();
}
<span class="fl-doc">/**
* Build a new SAX </span><span class="fl-doc"><span class="fl-constant">{@link Locator}</span></span><span class="fl-doc"> from a JAXP </span><span class="fl-doc"><span class="fl-constant">{@link SourceLocator}</span></span><span class="fl-doc">.
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">Locator</span> <span class="fl-function-name">jaxpToSaxLocator</span>(<span class="fl-type">SourceLocator</span> <span class="fl-variable-name">jaxp</span>)
{
<span class="fl-type">LocatorImpl</span> <span class="fl-variable-name">sax</span> = <span class="fl-keyword">new</span> <span class="fl-type">LocatorImpl</span>();
sax.setColumnNumber(jaxp.getColumnNumber());
sax.setLineNumber(jaxp.getLineNumber());
sax.setPublicId(jaxp.getPublicId());
sax.setSystemId(jaxp.getSystemId());
<span class="fl-keyword">return</span> sax;
}
<span class="fl-doc">/**
* Build a new JAXP </span><span class="fl-doc"><span class="fl-constant">{@link QName}</span></span><span class="fl-doc"> from a Saxon </span><span class="fl-doc"><span class="fl-constant">{@link StructuredQName}</span></span><span class="fl-doc">.
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">QName</span> <span class="fl-function-name">structuredToQName</span>(<span class="fl-type">StructuredQName</span> <span class="fl-variable-name">sname</span>)
{
<span class="fl-keyword">if</span> ( sname == null ) {
<span class="fl-keyword">return</span> null;
}
<span class="fl-type">String</span> <span class="fl-variable-name">uri</span> = sname.getNamespaceURI();
<span class="fl-type">String</span> <span class="fl-variable-name">local</span> = sname.getLocalName();
<span class="fl-type">String</span> <span class="fl-variable-name">prefix</span> = sname.getPrefix();
<span class="fl-keyword">return</span> <span class="fl-keyword">new</span> <span class="fl-type">QName</span>(uri, local, prefix);
}
<span class="fl-doc">/**
* Return a human-friendly view of the path to the current node if any.
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">String</span> <span class="fl-function-name">makePathToCurrentNode</span>(<span class="fl-type">XPathContext</span> <span class="fl-variable-name">ctxt</span>)
{
<span class="fl-type">SequenceIterator</span> <span class="fl-variable-name">it</span> = ctxt.getCurrentIterator();
<span class="fl-keyword">if</span> ( it == null ) {
<span class="fl-keyword">return</span> null;
}
<span class="fl-type">Item</span> <span class="fl-variable-name">item</span> = it.current();
<span class="fl-keyword">if</span> ( item <span class="fl-keyword">instanceof</span> NodeInfo ) {
<span class="fl-keyword">return</span> makePathTo((<span class="fl-type">NodeInfo</span>) item);
}
<span class="fl-keyword">return</span> null;
}
<span class="fl-doc">/**
* Return a human-friendly view of the path to a node within its document.
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">String</span> <span class="fl-function-name">makePathTo</span>(<span class="fl-type">NodeInfo</span> <span class="fl-variable-name">node</span>)
{
<span class="fl-keyword">if</span> ( node == null ) {
<span class="fl-keyword">return</span> null;
}
<span class="fl-type">String</span> <span class="fl-variable-name">path</span> = null;
<span class="fl-keyword">switch</span> ( node.getNodeKind() ) {
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.DOCUMENT: {
<span class="fl-keyword">return</span> <span class="fl-string">"/"</span>;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.ELEMENT: {
<span class="fl-type">String</span> <span class="fl-variable-name">name</span> = node.getNamePool().getDisplayName(node.getNameCode());
<span class="fl-type">AxisIterator</span> <span class="fl-variable-name">ai</span> = node.iterateAxis(<span class="fl-constant">Axis</span>.PRECEDING, <span class="fl-keyword">new</span> <span class="fl-type">NameTest</span>(node));
<span class="fl-type">int</span> <span class="fl-variable-name">pos</span> = 1;
<span class="fl-keyword">while</span> ( ai.moveNext() ) {
++ pos;
}
path = name + <span class="fl-string">"["</span> + pos + <span class="fl-string">"]"</span>;
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.ATTRIBUTE: {
<span class="fl-type">String</span> <span class="fl-variable-name">name</span> = node.getNamePool().getDisplayName(node.getNameCode());
path = <span class="fl-string">"@"</span> + name;
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.TEXT: {
<span class="fl-type">AxisIterator</span> <span class="fl-variable-name">ai</span> = node.iterateAxis(<span class="fl-constant">Axis</span>.PRECEDING, <span class="fl-constant">NodeKindTest</span>.TEXT);
<span class="fl-type">int</span> <span class="fl-variable-name">pos</span> = 1;
<span class="fl-keyword">while</span> ( ai.moveNext() ) {
++ pos;
}
path = <span class="fl-string">"text()["</span> + pos + <span class="fl-string">"]"</span>;
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.COMMENT: {
<span class="fl-type">AxisIterator</span> <span class="fl-variable-name">ai</span> = node.iterateAxis(<span class="fl-constant">Axis</span>.PRECEDING, <span class="fl-constant">NodeKindTest</span>.COMMENT);
<span class="fl-type">int</span> <span class="fl-variable-name">pos</span> = 1;
<span class="fl-keyword">while</span> ( ai.moveNext() ) {
++ pos;
}
path = <span class="fl-string">"comment()["</span> + pos + <span class="fl-string">"]"</span>;
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.PROCESSING_INSTRUCTION: {
<span class="fl-type">String</span> <span class="fl-variable-name">name</span> = node.getNamePool().getDisplayName(node.getNameCode());
<span class="fl-type">AxisIterator</span> <span class="fl-variable-name">ai</span> = node.iterateAxis(<span class="fl-constant">Axis</span>.PRECEDING, <span class="fl-keyword">new</span> <span class="fl-type">NameTest</span>(node));
<span class="fl-type">int</span> <span class="fl-variable-name">pos</span> = 1;
<span class="fl-keyword">while</span> ( ai.moveNext() ) {
++ pos;
}
path = <span class="fl-string">"processing-instruction("</span> + name + <span class="fl-string">")["</span> + pos + <span class="fl-string">"]"</span>;
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">case</span> <span class="fl-constant">Type</span>.NAMESPACE: {
<span class="fl-type">int</span> <span class="fl-variable-name">name_code</span> = node.getNameCode();
<span class="fl-type">String</span> <span class="fl-variable-name">name</span> = name_code < 0 ? <span class="fl-string">""</span> : node.getNamePool().getDisplayName(name_code);
<span class="fl-type">AxisIterator</span> <span class="fl-variable-name">ai</span> = node.iterateAxis(<span class="fl-constant">Axis</span>.PRECEDING, <span class="fl-keyword">new</span> <span class="fl-type">NameTest</span>(node));
<span class="fl-type">int</span> <span class="fl-variable-name">pos</span> = 1;
<span class="fl-keyword">while</span> ( ai.moveNext() ) {
++ pos;
}
path = <span class="fl-string">"namespace("</span> + name + <span class="fl-string">")["</span> + pos + <span class="fl-string">"]"</span>;
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">default</span>: {
<span class="fl-keyword">throw</span> <span class="fl-keyword">new</span> <span class="fl-type">RuntimeException</span>(<span class="fl-string">"FIXME: What to do?!?"</span>);
}
}
<span class="fl-type">String</span> <span class="fl-variable-name">parent</span> = makePathTo(node.getParent());
<span class="fl-keyword">if</span> ( parent == null ) {
<span class="fl-keyword">return</span> path;
}
<span class="fl-keyword">else</span> <span class="fl-keyword">if</span> ( <span class="fl-string">"/"</span>.equals(parent) ) {
<span class="fl-keyword">return</span> <span class="fl-string">"/"</span> + path;
}
<span class="fl-keyword">else</span> {
<span class="fl-keyword">return</span> parent + <span class="fl-string">"/"</span> + path;
}
}
<span class="fl-keyword">protected</span> <span class="fl-type">Locator</span> <span class="fl-variable-name">myLocator</span>;
<span class="fl-keyword">protected</span> <span class="fl-type">String</span> <span class="fl-variable-name">myPath</span>;
<span class="fl-keyword">private</span> <span class="fl-type">StackFrame</span> <span class="fl-variable-name">myNext</span>;
}
</pre>
<h3>FunctionFrame.java</h3>
<pre class="drkm-code-div">
<span class="fl-comment-delimiter">/*</span><span class="fl-comment">
* FunctionFrame.java
*
* Created on Oct 31, 2007, 8:10:37 PM
*/</span>
<span class="fl-keyword">package</span> saxon.xslt.<span class="fl-constant">stacktrace</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">namespace</span>.<span class="fl-type">QName</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">sax</span>.<span class="fl-type">Locator</span>;
<span class="fl-doc">/**
* Represent an XSLT stack frame for a function.
*
* </span><span class="fl-doc"><span class="fl-constant">@author</span></span><span class="fl-doc"> Florent Georges
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">FunctionFrame</span>
<span class="fl-keyword">extends</span> <span class="fl-type">StackFrame</span>
{
<span class="fl-doc">/**
* Build a new function frame.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> curr_item
* The path to the current node if any.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> name
* The name of the function.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> arity
* The arity of the function (its number of parameters).
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> locator
* The SAX locator for the function.
*/</span>
<span class="fl-keyword">public</span> FunctionFrame(<span class="fl-type">String</span> <span class="fl-variable-name">curr_item</span>, <span class="fl-type">QName</span> <span class="fl-variable-name">name</span>, <span class="fl-type">int</span> <span class="fl-variable-name">arity</span>, <span class="fl-type">Locator</span> <span class="fl-variable-name">locator</span>)
{
myPath = curr_item;
myName = name;
myArity = arity;
myLocator = locator;
}
<span class="fl-doc">/**
* Return the name of the function.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">QName</span> <span class="fl-function-name">getName</span>()
{
<span class="fl-keyword">return</span> myName;
}
<span class="fl-doc">/**
* Return the arity of the function (its number of parameters).
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">int</span> <span class="fl-function-name">getArity</span>()
{
<span class="fl-keyword">return</span> myArity;
}
@Override
<span class="fl-keyword">public</span> String toString()
{
<span class="fl-keyword">return</span> <span class="fl-string">"function "</span> + displayQName(myName) + <span class="fl-string">" #"</span> + myArity;
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">acceptVisitor</span>(<span class="fl-type">StackVisitor</span> <span class="fl-variable-name">visitor</span>)
{
visitor.visitFunctionFrame(<span class="fl-keyword">this</span>);
<span class="fl-keyword">if</span> ( getNext() != null ) {
getNext().acceptVisitor(visitor);
}
}
<span class="fl-keyword">private</span> <span class="fl-type">QName</span> <span class="fl-variable-name">myName</span>;
<span class="fl-keyword">private</span> <span class="fl-type">int</span> <span class="fl-variable-name">myArity</span>;
}
</pre>
<h3>TemplateFrame.java</h3>
<pre class="drkm-code-div">
<span class="fl-comment-delimiter">/*</span><span class="fl-comment">
* TemplateFrame.java
*
* Created on Oct 31, 2007, 8:09:11 PM
*/</span>
<span class="fl-keyword">package</span> saxon.xslt.<span class="fl-constant">stacktrace</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">namespace</span>.<span class="fl-type">QName</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">org</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">sax</span>.<span class="fl-type">Locator</span>;
<span class="fl-doc">/**
* Represent an XSLT stack frame for a template.
*
* </span><span class="fl-doc"><span class="fl-constant">@author</span></span><span class="fl-doc"> Florent Georges
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">TemplateFrame</span>
<span class="fl-keyword">extends</span> <span class="fl-type">StackFrame</span>
{
<span class="fl-doc">/**
* Build a new template frame.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> curr_item
* The path to the current node if any.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> pattern
* The pattern the template matches, if it is a template rule.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> name
* The name of the template, if it is a named template.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> mode
* The mode of the template, if any.
*
* </span><span class="fl-doc"><span class="fl-constant">@param</span></span><span class="fl-doc"> locator
* The SAX locator for the template.
*/</span>
<span class="fl-keyword">public</span> TemplateFrame(<span class="fl-type">String</span> <span class="fl-variable-name">curr_item</span>, <span class="fl-type">String</span> <span class="fl-variable-name">pattern</span>, <span class="fl-type">QName</span> <span class="fl-variable-name">name</span>, <span class="fl-type">QName</span> <span class="fl-variable-name">mode</span>, <span class="fl-type">Locator</span> <span class="fl-variable-name">locator</span>)
{
myPath = curr_item;
myPattern = pattern;
myName = name;
myMode = mode;
myLocator = locator;
myCalled = false;
}
<span class="fl-doc">/**
* Return the pattern of the template, if it is a template rule.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">String</span> <span class="fl-function-name">getPattern</span>()
{
<span class="fl-keyword">return</span> myPattern;
}
<span class="fl-doc">/**
* Return the name of the template if it is a named template.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">QName</span> <span class="fl-function-name">getName</span>()
{
<span class="fl-keyword">return</span> myName;
}
<span class="fl-doc">/**
* Return the mode's name of the template, if it is a template rule and has a mode.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">QName</span> <span class="fl-function-name">getMode</span>()
{
<span class="fl-keyword">return</span> myMode;
}
<span class="fl-doc">/**
* Set the mode of the template.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">setMode</span>(<span class="fl-type">QName</span> <span class="fl-variable-name">mode</span>)
{
myMode = mode;
}
<span class="fl-doc">/**
* Return </span><span class="fl-doc"><span class="fl-constant">{@code true}</span></span><span class="fl-doc"> if the template was called, </span><span class="fl-doc"><span class="fl-constant">{@code false}</span></span><span class="fl-doc"> if it was applied.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">boolean</span> <span class="fl-function-name">isCalled</span>()
{
<span class="fl-keyword">return</span> myCalled;
}
<span class="fl-doc">/**
* Set the </span><span class="fl-doc"><span class="fl-constant">{@code isCalled}</span></span><span class="fl-doc"> property of the template (see </span><span class="fl-doc"><span class="fl-constant">{@link #isCalled()}</span></span><span class="fl-doc">).
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">setCalled</span>(<span class="fl-type">boolean</span> <span class="fl-variable-name">called</span>)
{
myCalled = called;
}
@Override
<span class="fl-keyword">public</span> String toString()
{
<span class="fl-type">StringBuilder</span> <span class="fl-variable-name">buf</span> = <span class="fl-keyword">new</span> <span class="fl-type">StringBuilder</span>(<span class="fl-string">"template "</span>);
<span class="fl-keyword">if</span> ( myName != null ) {
buf.append(displayQName(myName)).append(<span class="fl-string">' '</span>);
}
<span class="fl-keyword">if</span> ( myMode != null ) {
buf.append(<span class="fl-string">'#'</span>).append(displayQName(myMode)).append(<span class="fl-string">' '</span>);
}
<span class="fl-keyword">if</span> ( myPattern != null ) {
buf.append(<span class="fl-string">"matching "</span>).append(<span class="fl-string">'\"'</span>).append(myPattern).append(<span class="fl-string">'\"'</span>);
}
<span class="fl-keyword">return</span> buf.toString();
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">acceptVisitor</span>(<span class="fl-type">StackVisitor</span> <span class="fl-variable-name">visitor</span>)
{
visitor.visitTemplateFrame(<span class="fl-keyword">this</span>);
<span class="fl-keyword">if</span> ( getNext() != null ) {
getNext().acceptVisitor(visitor);
}
}
<span class="fl-keyword">private</span> <span class="fl-type">String</span> <span class="fl-variable-name">myPattern</span>;
<span class="fl-keyword">private</span> <span class="fl-type">QName</span> <span class="fl-variable-name">myName</span>;
<span class="fl-keyword">private</span> <span class="fl-type">QName</span> <span class="fl-variable-name">myMode</span>;
<span class="fl-keyword">private</span> <span class="fl-type">boolean</span> <span class="fl-variable-name">myCalled</span>;
}
</pre>
<h3>StackVisitor.java</h3>
<pre class="drkm-code-div">
<span class="fl-comment-delimiter">/*</span><span class="fl-comment">
* StackFrameVisitor.java
*
* Created on Oct 31, 2007, 8:14:12 PM
*/</span>
<span class="fl-keyword">package</span> saxon.xslt.<span class="fl-constant">stacktrace</span>;
<span class="fl-doc">/**
* Visitor that visits an XSLT stack.
*
* </span><span class="fl-doc"><span class="fl-constant">@see</span></span><span class="fl-doc"> </span><span class="fl-doc"><span class="fl-constant">{@link StackFrame#acceptVisitor(StackFrameVisitor)}</span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant">@author</span></span><span class="fl-doc"> Florent Georges
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">interface</span> <span class="fl-type">StackVisitor</span>
{
<span class="fl-doc">/**
* Visit a function frame.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">visitFunctionFrame</span>(<span class="fl-type">FunctionFrame</span> <span class="fl-variable-name">frame</span>);
<span class="fl-doc">/**
* Visit a template frame.
*/</span>
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">visitTemplateFrame</span>(<span class="fl-type">TemplateFrame</span> <span class="fl-variable-name">frame</span>);
}
</pre>
<h3>Main.java</h3>
<pre class="drkm-code-div">
<span class="fl-comment-delimiter">/*</span><span class="fl-comment">
* Main.java
*
* Created on Oct 27, 2007, 1:21:32 PM
*/</span>
<span class="fl-keyword">package</span> saxon.xslt.<span class="fl-constant">stacktrace</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">io</span>.<span class="fl-type">File</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">ErrorListener</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">Source</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">Transformer</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">TransformerException</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-type">TransformerFactory</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-constant">stream</span>.<span class="fl-type">StreamResult</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">javax</span>.<span class="fl-constant">xml</span>.<span class="fl-constant">transform</span>.<span class="fl-constant">stream</span>.<span class="fl-type">StreamSource</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-type">TransformerFactoryImpl</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">XPathException</span>;
<span class="fl-doc">/**
* Sample application that run a stylesheet an output the XSLT stacktrace in case of error.
*
* </span><span class="fl-doc"><span class="fl-constant"><p></span></span><span class="fl-doc">The stylesheet used is </span><span class="fl-doc"><span class="fl-constant">{@code src/saxon/xslt/stacktrace/style.xsl}</span></span><span class="fl-doc">.</span><span class="fl-doc"><span class="fl-constant"></p></span></span><span class="fl-doc">
*
* </span><span class="fl-doc"><span class="fl-constant">@author</span></span><span class="fl-doc"> Florent Georges
*/</span>
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">Main</span>
{
<span class="fl-keyword">public</span> <span class="fl-keyword">static</span> <span class="fl-type">void</span> <span class="fl-function-name">main</span>(<span class="fl-type">String</span>[] <span class="fl-variable-name">args</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">TransformerException</span>
{
<span class="fl-type">TransformerFactory</span> <span class="fl-variable-name">factory</span> = TransformerFactoryImpl.newInstance();
<span class="fl-type">Source</span> <span class="fl-variable-name">style</span> = <span class="fl-keyword">new</span> <span class="fl-type">StreamSource</span>(<span class="fl-keyword">new</span> <span class="fl-type">File</span>(<span class="fl-string">"src/saxon/xslt/stacktrace/style.xsl"</span>));
<span class="fl-type">Transformer</span> <span class="fl-variable-name">trans</span> = factory.newTransformer(style);
trans.setErrorListener(<span class="fl-keyword">new</span> <span class="fl-type">NullErrorListener</span>());
<span class="fl-keyword">try</span> {
trans.transform(style, <span class="fl-keyword">new</span> <span class="fl-type">StreamResult</span>(System.out));
}
<span class="fl-keyword">catch</span> ( <span class="fl-type">XPathException</span> <span class="fl-variable-name">ex</span> ) {
System.err.println(ex.getErrorCodeLocalPart() + <span class="fl-string">": "</span> + ex.getMessage());
<span class="fl-type">StackFrame</span> <span class="fl-variable-name">stack</span> = StackFrame.makeStack(ex);
<span class="fl-type">DisplayerStackVisitor</span> <span class="fl-variable-name">visitor</span> = <span class="fl-keyword">new</span> <span class="fl-type">DisplayerStackVisitor</span>();
stack.acceptVisitor(visitor);
visitor.finish();
}
}
<span class="fl-doc">/**
* Does nothing, to supress error messages from Saxon itself.
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-keyword">class</span> <span class="fl-type">NullErrorListener</span>
<span class="fl-keyword">implements</span> <span class="fl-type">ErrorListener</span>
{
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">warning</span>(<span class="fl-type">TransformerException</span> <span class="fl-variable-name">ex</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">TransformerException</span> {
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">error</span>(<span class="fl-type">TransformerException</span> <span class="fl-variable-name">ex</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">TransformerException</span> {
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">fatalError</span>(<span class="fl-type">TransformerException</span> <span class="fl-variable-name">ex</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">TransformerException</span> {
}
}
<span class="fl-doc">/**
* Stack visitor that display the stack as text on </span><span class="fl-doc"><span class="fl-constant">{@code System.err}</span></span><span class="fl-doc">.
*/</span>
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-keyword">class</span> <span class="fl-type">DisplayerStackVisitor</span>
<span class="fl-keyword">implements</span> <span class="fl-type">StackVisitor</span>
{
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">visitFunctionFrame</span>(<span class="fl-type">FunctionFrame</span> <span class="fl-variable-name">frame</span>)
{
doVisit(frame);
myHead = <span class="fl-string">" called "</span>;
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">visitTemplateFrame</span>(<span class="fl-type">TemplateFrame</span> <span class="fl-variable-name">frame</span>)
{
doVisit(frame);
myHead = frame.isCalled() ? <span class="fl-string">" called "</span> : <span class="fl-string">" applied "</span>;
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">finish</span>()
{
System.err.println(myHead + <span class="fl-string">"from external application"</span>);
}
<span class="fl-keyword">private</span> <span class="fl-type">void</span> <span class="fl-function-name">doVisit</span>(<span class="fl-type">StackFrame</span> <span class="fl-variable-name">frame</span>)
{
<span class="fl-type">int</span> <span class="fl-variable-name">line</span> = frame.getLocator().getLineNumber();
<span class="fl-type">int</span> <span class="fl-variable-name">col</span> = frame.getLocator().getColumnNumber();
<span class="fl-type">String</span> <span class="fl-variable-name">pos</span> = getFile(frame) + <span class="fl-string">":"</span> + line + ( col < 0 ? <span class="fl-string">""</span> : <span class="fl-string">":"</span> + col );
System.err.println(myHead + <span class="fl-string">"in "</span> + frame + <span class="fl-string">" (at "</span> + pos + <span class="fl-string">")"</span>);
<span class="fl-type">String</span> <span class="fl-variable-name">path</span> = frame.getPath();
<span class="fl-keyword">if</span> ( path != null ) {
System.err.println(<span class="fl-string">" `-> "</span> + path);
}
}
<span class="fl-keyword">private</span> <span class="fl-keyword">static</span> <span class="fl-type">String</span> <span class="fl-function-name">getFile</span>(<span class="fl-type">StackFrame</span> <span class="fl-variable-name">frame</span>)
{
<span class="fl-type">String</span> <span class="fl-variable-name">sysid</span> = frame.getLocator().getSystemId();
<span class="fl-type">int</span> <span class="fl-variable-name">slash</span> = sysid.lastIndexOf(<span class="fl-string">'/'</span>);
<span class="fl-keyword">if</span> ( slash < 0 ) {
<span class="fl-keyword">return</span> sysid;
}
<span class="fl-keyword">else</span> {
<span class="fl-keyword">return</span> sysid.substring(slash + 1);
}
}
<span class="fl-keyword">private</span> <span class="fl-type">String</span> <span class="fl-variable-name">myHead</span> = <span class="fl-string">" "</span>;
}
}
</pre>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com9tag:blogger.com,1999:blog-33074681.post-7770522589666319922007-06-30T23:22:00.000+02:002007-06-30T23:31:32.604+02:00Error handling extension for XSLT 2.0<p>I finally wrote a few words about the try/catch extension I wrote for Saxon a couple of months ago (see <a href="http://fgeorges.blogspot.com/2007/01/trycatch-in-xslt-20-first-test-cases.html">this</a> and <a href="http://fgeorges.blogspot.com/2007/01/trycatch-in-xslt-20.html">this</a> entries). You can find the project page there: <a href="http://www.fgeorges.org/xslt/error-safe/">http://www.fgeorges.org/xslt/error-safe/</a>.</p>
<p>I also wrote a first draft of a specification for such an extension. There are some differences between this and the actual implementation for Saxon, but the spirit remains the same. It can be found there: <a href="http://www.fgeorges.org/xslt/error-safe/error-safe.html">http://www.fgeorges.org/xslt/error-safe/error-safe.html</a>.</p>
<p>I don't know if the <a href="http://exslt.org/">EXSLT project</a> is open to extensions for XSLT 2.0. I think that would be worth having an error handling extension defined in such a vendor-neutral project. I'm indeed interested in any comments about this extension and its specification.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com2tag:blogger.com,1999:blog-33074681.post-51688304171724655322007-06-24T23:56:00.000+02:002007-06-25T00:01:56.531+02:00Relax NG Compact schema for Ant build files<p>Someone asked a few days ago on the <a href="http://www.thaiopensource.com/nxml-mode/">nXML</a> mailing list a question about a schema for Ant build files, in <a href="http://comments.gmane.org/gmane.emacs.nxml.general/1513">this thread</a>. Steinar Bang came with a schema he generated from a sample Ant build file.</p>
<p>A specific Ant task generated a DTD from the content of this build file, then he transformed it to a Relax NG Compact schema. This is not a rigorous schema, but this would be enough as a basis to edit Ant build files with nXML and get completion.</p>
<p>The schema can be found at: <a href="http://www.fgeorges.org/purl/20070624/ant.rnc">http://www.fgeorges.org/purl/20070624/ant.rnc</a>.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-3055662138887178592007-05-14T23:41:00.000+02:002007-05-14T23:42:29.757+02:00XML Catalogs support in Saxon 8 for Java<p>Saxon doesn't support OASIS's XML Catalogs natively. But adding
this support yourself is quite easy. You need the <a
href="http://xml.apache.org/mirrors.cgi#binary">XML Commons
Resolver</a> from Apache. Make sure the JAR <code>resolver.jar</code>
you will find in the archive is in you classpath. Then you need to
call Saxon with the following options:</p>
<pre class="drkm-code-div">
java -cp <saxon and resolver jars> \
-Dxml.catalog.files=<the catalog files> \
-Dxml.catalog.verbosity=1 \
net.sf.saxon.Transform \
-r org.apache.xml.resolver.tools.CatalogResolver \
-x org.apache.xml.resolver.tools.ResolvingXMLReader \
-y org.apache.xml.resolver.tools.ResolvingXMLReader \
<other options>
</pre>
<p>That's it!</p>
<p>You can also use my shell script to launch Saxon, that supports
catalogs through additional options (see <a
href="http://www.fgeorges.org/xslt/launchers/">the script page</a> or
<a
href="http://fgeorges.blogspot.com/2007/01/shell-script-to-launch-saxon.html">this
post</a>):</p>
<pre class="drkm-code-div">
saxon --catalogs=<the catalog files> <other options>
</pre>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-1169133932114814352007-01-18T16:24:00.000+01:002007-05-15T00:05:32.287+02:00Creating namespace nodes in XSLT 1.0<h2>Introduction and motivating example</h2>
<p>This entry discusses the better way to add namespace
nodes to an element in XSLT 1.0. The goal is to try to have
the right namespace bindings in context for content using
them, as attribute values storing XPath expressions. There
is no way to guarantee it, but the code developed below is
reasonable enough to work in most cases.</p>
<p>In addition to showing how to generate a namespace node
in the result tree, this entry discusses specific problems
and tricks when employed in a <a
href="http://2006.xmlconference.org/programme/presentations/26.html">meta-stylesheet</a>,
and how to use the XSLT 2.0 instruction
<code>xsl:namespace</code> when available.</p>
<p>The motivating case is the base meta-stylesheet (the
<em>skeleton</em>) currently developped for <a
href="http://www.schematron.com/">ISO Schematron</a>. <a
href="http://eccnet.eccnet.com/pipermail/schematron-love-in/">Schematron
Love In</a>, the mailing list for Schematron, was very
active these last days, after Rick posted a first draft of
the skeleton for ISO Schematron. One of the most discussed
points was <em>How to have the correct namespace bindings in
the generated stylesheet?</em> But here is an example
first, with a little explanation, before going further:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name"><span class="fl-rng-error">schema</span></span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://purl.oclc.org/dsdl/schematron</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ns</span> <span class="fl-nxml-attribute-local-name">prefix</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">uri</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">http://www.fgeorges.org/</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Sample schema</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">title</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">pattern</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Test schema</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">rule</span> <span class="fl-nxml-attribute-local-name">context</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">fg:elem</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">assert</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">@id</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">'fg:elem' must have an @id.</span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">assert</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">rule</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">pattern</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">schema</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Namespaces used in the attribute contents are declared by
the element <code>ns</code>. For each node in the tested
document matching the <code>rule/@context</code> match
pattern, the XPath expression in <code>assert/@test</code>
is evaluated and must be true. If not, an error is
reported. The more natural way to implement this language
is generating an XSLT stylesheet, and the more natural way
to generate it is using an XSLT meta-stylesheet.</p>
<h2>Generating a namespace binding in XSLT 1.0</h2>
<p>There is no way to guarantee, in an XSLT 1.0 stylesheet,
that the output tree will contain a namespace binding for a
specified prefix. The serializer is permitted to change any
prefix in the output tree, providing that the prefix is
still bound to the right URI. This is convenient to not
worry about to bindings to the same prefix. The serializer
change one prefix, and all is fine.</p>
<p>All? Really? All is fine regarding names of elements
and attributes in the output tree (this is what nemspaces
are about), but not regarding the attribute values using
them, for example. If one attribute value is
<code>"fg:elem"</code> as above, and the serializer change
the prefix to <code>ns1</code> (changing also all element
and attribute names in this namespace), the attribute value
cannot be interpreted as an XPath expression anymore. And
if a nemspace binding is not used (if no element or
attribute is n this namespace), the serializer can drop the
namespace binding.</p>
<p>The usual trick to add a namespace node to an element is
to use one of the <code>xxx:node-set()</code> functions like
the following:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> In the stylesheet. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">elem</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ns</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">elem</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://uri</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">exsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">elem</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> In the result tree (in most cases). </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name"><span class="fl-rng-error">elem</span></span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://uri</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>If a <code>xxx:node-set()</code> extension function is
not available, the only way to add a namespace binding in
the result tree is to add an element or an attribute in the
namespace to the result tree. In a meta-stylesheet, we can
add an attribute to an XSLT instruction, if this attribute
is not in the null namespace or in the XSLT namespace (say
we don't use extensions in the generated stylesheet):</p>
<pre class="drkm-code-div">
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> In the stylesheet. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name"><span class="fl-rng-error">elem</span></span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">attribute</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ns:dummy-for-xmlns</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://uri</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">elem</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> In the result tree (in most cases). </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name"><span class="fl-rng-error">elem</span></span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ns</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://uri</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-prefix">ns</span><span class="fl-nxml-attribute-colon">:</span><span class="fl-nxml-attribute-local-name">dummy-for-xmlns</span>=<span class="fl-nxml-attribute-value-delimiter">""</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>So we can write a named template to handle all of
this:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">make-namespace-node</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">prefix</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">uri</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> All supported node-set() functions. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">function-available('exsl:node-set')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">element</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }:e</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">exsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">function-available('msxsl:node-set')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">element</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }:e</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">msxsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> If no node-set() available. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">attribute</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ concat($prefix, ':dummy-for-xmlns') }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<h2>Back to Schematron</h2>
<p>The skeleton for ISO Schematron is a meta-stylesheet.
That means the result tree of the transformation is itself
an XSLT stylesheet. The <code>ns</code> element in
Schematron appear as childs of the root element. The goal
is to generate namespace declarations on the generated
element <code>xsl:stylesheet</code>. Are there some
specificities we have to take care to?</p>
<p>There is one for sure. In the case a
<code>xxx:node-set()</code> function is not available, we
are creating a dummy attribute on the
<code>xsl:stylesheet</code>. But this cannot be an
attribute in the XSLT namespace. If it was, the XSLT
processor would say it doesn't know this attribute when
running the generated stylesheet, and report an error.</p>
<p>An error that can occurs is trying to add a namespace
node with the same name of a namespace node already
existsing on the element, but bound to another URI. But we
cannot know all prefixes used in the generated stylesheet.
The only thing we can do, I think, is asking schema authors
to not bind usual prefixes to other URIs they are usually
bound to. For example, if you really want to use the
<code>xsl</code> prefix for the XSLT namespace, no problem.
If you want to use it for your own namespace URI, accept all
consequences.</p>
<p>But I'm affraid no check can be done formally. So here
is what the template now looks for:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">make-namespace-node</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">prefix</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">uri</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> EXSLT's node-set(). </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">function-available('exsl:node-set')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">element</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }:e</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">exsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> MSXSL's node-set(). </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">function-available('msxsl:node-set')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">element</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }:e</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">msxsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> If no node-set(), cannot handle XSLT namespace. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">@uri = 'http://www.w3.org/1999/XSL/Transform'</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">message</span> <span class="fl-nxml-attribute-local-name">terminate</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Using the XSLT namespace in Schematron </span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">rules is not supported in this processor: </span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">system-property('xsl:vendor')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">message</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> If no node-set(), dummy attribute trick. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl</span></span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">attribute</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ concat($prefix, ':dummy-for-xmlns') }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<h2>Is it possible to use <code>xsl:namespace</code> if
available?</h2>
<p>This entry discusses only generating namespace nodes in
an XSLT 1.0 stylesheet, because in XSLT 2.0 tere is the
<code>xsl:namespace</code> that does this job. But an XSLT
1.0 stylesheet can be run by an XSLT 2.0 processor. And in
this case it can uses XSLT 2.0 instructions. How to do that
in a reliabe way?</p>
<p>If we add <code>xsl:namespace</code> in the XSLT 1.0
stylesheet, XSLT 1.0 processors will generate a compilation
error, telling you that you probably made a mistake because
you use an unknown XSLT instruction. Don't try to lie to
your processor, and tell it the truth: that piese of code is
actually XSLT 2.0 code. How? Simply by creating an
external stylesheet module with <code>@version="2.0"</code>.</p>
<p>Obviously, XSLT 2.0 processors will not have problem
here. And XSLT 1.0 processors? They will run (for this
module) in <em>forwards-compatible</em> mode. So they will
not generate compilation error for XSLT instructions they
don't know, but you still have to prevent them to actually
instantiate these instructions. It is easy with
<code>element-available()</code>:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix"><span class="fl-rng-error">xsl:stylesheet</span></span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">make-namespace-node</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">prefix</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">uri</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> In XSLT 2.0. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">element-available('xsl:namespace')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">namespace</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$uri</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> EXSLT's node-set(). </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">function-available('exsl:node-set')</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">use-when</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">false()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">element</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }:e</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">exsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> MSXSL's node-set(). </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">function-available('msxsl:node-set')</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">use-when</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">false()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">dummy</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">element</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $prefix }:e</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">copy-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">msxsl:node-set($dummy)/*/namespace::*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> If no node-set(), cannot handle XSLT namespace. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span> <span class="fl-nxml-attribute-local-name">test</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">@uri = 'http://www.w3.org/1999/XSL/Transform'</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">use-when</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">false()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">message</span> <span class="fl-nxml-attribute-local-name">terminate</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">Using the XSLT namespace in Schematron </span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span><span class="fl-nxml-text">rules is not supported in this processor: </span><span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">text</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">system-property('xsl:vendor')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">message</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">when</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content"> If no node-set(), dummy attribute trick. </span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span> <span class="fl-nxml-attribute-local-name">use-when</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">false()</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">attribute</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ concat($prefix, ':dummy-for-xmlns') }</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">namespace</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ $uri }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">otherwise</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">choose</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Note the <code>@version="2.0"</code> and the use of
<code>@use-when</code>. With an XSLT 2.0 processor, that
will cause the other branches to be even not compiled. With
an XSLT 1.0 processor, that will have no effect, because it
doesn't know this attribute.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com1tag:blogger.com,1999:blog-33074681.post-1168609841783189972007-01-12T14:48:00.000+01:002007-01-22T00:36:32.846+01:00Gexslt: using the CVS version<p>This entry is a short comment describing how to download,
set up and compile Gexslt from the CVS repository. <a
href="http://gobo-eiffel.sf.net/gexslt/">Gexslt</a> is an
XSLT 2.0 processor written in Eiffel by Colin Adams, and is
part of the <a href="http://gobo-eiffel.sf.net/">Gobo</a>
project.</p>
<p>This entry is not a comprehensive documentation. On
contrary, it is a short explanation for non-Eiffel
programmers that want to <em>use</em> the last version of
Gexslt. The fewer steps are described here, the better. I
also describe my own setup; it is on Windows, with
EiffelStudio.</p>
<p>So you first need an Eiffel compiler. Then you need the
Gobo source code. A few environment variables have to be
setup. Then you can compile Gexslt. I'll describe at the
end how to update your copy of Gexslt to include the last
fixes.</p>
<h2>Initial setup</h2>
<p>Gobo comes with its own Eiffel compiler: <code>gec</code>. I don't use it because I had troubles to install it the first time I compiled Gexslt. So I describe the use of EiffelStudio (the compiler I use). Feel free to see the Gobo documentation to use <code>gec</code> instead.</p>
<p>Download EiffelStudio from <a
href="http://www.eiffel.com/products/studio/">http://www.eiffel.com/products/studio/</a>.
Just follow the instructions there to install the software.
Basically, you can download the installer, run it, then push
on "Next", "Next"... Say you installed it in
<code>C:\Eiffel57</code>. Install the Borland C++ compiler
shipped with EiffelStudio: just say "Yes" when the installer
ask you for (if you already have MSC compiler, you can avoid
installing the Borland one, and try to use MSC instead; see
the Gobo documentation).</p>
<p><b>Warning</b>: It is strongly recommended to install
EiffelStudio in a path without any space (for example, try
to avoid <code>C:\Program Files</code>), as it may result in
an error in the Gobo build process! If you want to save
time to yourself, install it for example in
<code>C:\Eiffel57</code>.</p>
<p>To get the source code for Gobo (including Gexslt) from its
CVS repository, you need to use your favorite CVS client.
With the command-line client from <a
href="http://cvshome.org/">http://cvshome.org/</a>, you can
use the following to check out the sources (but you can put
these information in your graphical client if you prefer,
as the one for Eclipse):</p>
<pre class="drkm-code-div">
cvs -d :pserver:anonymous@gobo-eiffel.cvs.sf.net:/cvsroot/gobo-eiffel co gobo
</pre>
<p>That will create a <code>gobo</code> directory in the
current directory. Say you are in <code>C:\</code>, so that
will create <code>C:\gobo</code>.</p>
<p>Now the environment variables. You need to create a
variable to say where is the Gobo directory, as well as
updating your <code>%PATH%</code> in order to the build
system will find the Eiffel and C compilers. So create the
<code>%GOBO%</code> variable with the value
<code>C:\gobo</code> (or whatever you actually used), and
add both <code>C:\Eiffel57\BCC55\Bin</code> and
<code>C:\Eiffel57\studio\spec\windows\bin</code> to your
<code>%PATH%</code>.</p>
<p>Now you can compile Gobo. Just go to Gobo directory and
run:</p>
<pre class="drkm-code-div">
.\work\bootstrap\bootstrap.bat bcc ise
</pre>
<p>Now go to make a coffe, or even go to lunch, that step
will take a long time. After the compilation complete, you
can use <code>C:\gobo\bin\gexslt.exe</code> from the command
line to run XSLT 2.0 transformations.</p>
<p>But that is not the end of the story. If you are ready to
do all this work to can use Gexslt from its CVS, you will
probably be interested in two additional steps: compiling
Gexslt with debug output enabled, and updating your copy
with the last CVS state.</p>
<p>To enable the debug output, just go the the
<code>C:\gobo\src\gexslt</code> and run <code>geant
compile_debug_ise</code>. That will create the executable
<code>C:\gobo\src\gexslt\gexslt.exe</code>. My advice is to
not move it to <code>C:\gobo\bin</code>, so you keep both
versions, with and without debug info. It is usefull,
because the debug enabled version takes a lot of time more
than the normal version.</p>
<p>So to resume all the steps for the initial setup:</p>
<pre class="drkm-code-div">
rem Install EiffelStudio
rem Create %GOBO% = C:\gobo
rem Add both C:\Eiffel57\BCC55\Bin and
rem C:\Eiffel57\studio\spec\windows\bin
rem to your %PATH%
rem Go to C:\ in a command prompt
C:
rem Get Gobo sources
cvs -d :pserver:anonymous@gobo-eiffel.cvs.sf.net:/cvsroot/gobo-eiffel co gobo
rem Compile Gobo the first time
work\bootstrap\bootstrap.bat bcc ise
rem Compile Gexslt with debug support
cd src\gexslt
geant compile_debug_ise
rem Now you can use C:\gobo\bin\gexslt.exe and
rem C:\gobo\src\gexslt\gexslt.exe (with debug support)
</pre>
<h2>Updates</h2>
<p>To update your Gexslt, just update your local copy of the
Gobo repository with your prefered CVs client. For example
with the command-line CVS client, just go to
<code>C:\gobo</code>, then run <code>cvs update -dP</code>.
To recompile, run first <code>geant install</code> within
<code>C:\gobo</code> and then both <code>geant compile_ise</code>
and <code>geant compile_debug_ise</code> within
<code>C:\gobo\src\gexslt</code>, to recompile both the
normal and the debug-enabled versions (don't forget to copy
<code>gexslt.exe</code> between the two compilation phases!):</p>
<pre class="drkm-code-div">
cd C:\gobo
cvs update -dp
geant install
cd src\gexslt
geant compile_ise
copy gexslt.exe C:\gobo\bin
geant compile_debug_ise
</pre>
<p>I think there is all that is needed by an XSLT developer
working on Windows to can use Gexslt from the CVS.</p>
<p>If you think you find a bug in Gexslt, you can use the
following <a
href="http://sourceforge.net/mailarchive/forum.php?forum_id=43093">mailing
list</a> to report it.</p>
<p>Thanks Colin for your work!</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com4tag:blogger.com,1999:blog-33074681.post-1168388437527520812007-01-10T01:19:00.000+01:002007-01-10T01:35:47.920+01:00Try/catch in XSLT 2.0: first test cases, first problems<h2>Introduction</h2>
<p>In addition to a comment and some advices on <a href="http://fgeorges.blogspot.com/2007/01/trycatch-in-xslt-20.html">Try/catch in XSLT 2.0</a>, Michael Kay gave me today in a <a href="http://sourceforge.net/mailarchive/message.php?msg_id=37863852">post on the Saxon mailing list</a> four interesting test cases. The comment and advices say:</p>
<blockquote cite="http://sourceforge.net/mailarchive/message.php?msg_id=37863852">
<p>The design of this from the user perspective looks reasonable: it's better than my <a href="http://www.saxonica.com/documentation/extensions/functions/try.html">own attempt</a> to do it solely using extension functions. I did it that way because I was targetting XQuery, but it's not ideal there either, if only because saxon:try() is not a true function.</p>
<p>The tricky part in doing try/catch properly, however, is the semantics. You need to make sure, as far as possible, that (a) you don't catch errors in expressions that are written outside the try but lazily evaluated within it, and (b) that you do catch errors in expressions that are written inside the try but lazily evaluated outside it. This involves both compile-time work, to suppress rewrites that move expressions into or out of the try block, and run-time work, to suppress lazy evaluation (or to make sure that lazily-evaluated expressions carry their catch block with them)</p>
</blockquote>
<p>So I created a real test case for each of his test case advice, and added one more, more severe IMHO. Actually, three of his test cases passed, and one failed. The fifth one cause an illegal state in the serializer.</p>
<p>Thank you again Mike for your input!</p>
<h2>Results</h2>
<p>Here is first the output of the test cases, then each test case individually with a few words.</p>
<pre class="drkm-code-div">
(drkm) [168]> saxon --b --add-cp=fgeorges.jar -it main error-safe-01.xsl
<root>
<div-by-0 i="1"/>
<div-by-0 i="2"/>
<div-by-0 i="3"/>
<div-by-0 i="4"/>
<div-by-0 i="5"/>
<div-by-0 i="6"/>
<div-by-0 i="7"/>
<div-by-0 i="8"/>
<div-by-0 i="9"/>
<div-by-0 i="10"/>
</root>
(drkm) [169]> saxon --b --add-cp=fgeorges.jar -it main error-safe-02.xsl
<root>
<div-by-0 where="In main."/>
</root>
(drkm) [170]> saxon --b --add-cp=fgeorges.jar -it main error-safe-03.xsl
<root>
<ERROR what="Div by 0" where="In main!"/>
</root>
(drkm) [171]> saxon --b --add-cp=fgeorges.jar -it main error-safe-04.xsl
<root>
<div-by-0/>
</root>
(drkm) [172]> saxon --b --add-cp=fgeorges.jar -it main error-safe-05.xsl
java.lang.IllegalStateException: Attempt to end document in serializer when elements are unclosed
at net.sf.saxon.event.XMLEmitter.endDocument(XMLEmitter.java:110)
at net.sf.saxon.event.ProxyReceiver.endDocument(ProxyReceiver.java:102)
at net.sf.saxon.event.ProxyReceiver.endDocument(ProxyReceiver.java:102)
at net.sf.saxon.event.ProxyReceiver.endDocument(ProxyReceiver.java:102)
at net.sf.saxon.event.ProxyReceiver.endDocument(ProxyReceiver.java:102)
at net.sf.saxon.event.ComplexContentOutputter.endDocument(ComplexContentOutputter.java:115)
at net.sf.saxon.Controller.transformDocument(Controller.java:1654)
at net.sf.saxon.Controller.transform(Controller.java:1438)
at net.sf.saxon.Transform.execute(Transform.java:890)
at net.sf.saxon.Transform.doTransform(Transform.java:491)
at net.sf.saxon.Transform.main(Transform.java:60)
Fatal error during transformation: Attempt to end document in serializer when elements are unclosed
(drkm) [173]>
</pre>
<h2><code>error-safe-01.xsl</code></h2>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ex</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:/org.fgeorges.exslt2.saxon.Exslt2InstructionFactory</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">extension-element-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ex</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">omit-xml-declaration</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Test from Michael Kay, see http://sf.net/mailarchive/message.php?msg_id=37863852
(the danger here is that the 1 div $zero, being independent of
the loop context, will be evaluated outside the loop. This might
be OK: In fact, I think it probably will be OK, because although
Saxon moves the expression outside the loop, it always evaluates
it lazily to avoid triggering errors if the loop is executed
zero times. But it needs testing).
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">call-template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ERROR</span> <span class="fl-nxml-attribute-local-name">what</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Div by 0 error not caught!</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">zero</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1 to 10</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1 div $zero</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">div-by-0</span> <span class="fl-nxml-attribute-local-name">i</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ . }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<h2><code>error-safe-02.xsl</code></h2>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ex</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:/org.fgeorges.exslt2.saxon.Exslt2InstructionFactory</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">extension-element-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ex</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">omit-xml-declaration</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Test from Michael Kay, see http://sf.net/mailarchive/message.php?msg_id=37863852
Here the error shouldn't be caught, but it might be, because of
lazy evaluation.
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">call-template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">div-by-0</span> <span class="fl-nxml-attribute-local-name">where</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">In main.</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">zero</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">v</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">for $n in 1 to 10 return $n div $zero</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1 to 10</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">$v[current()]</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ERROR</span> <span class="fl-nxml-attribute-local-name">what</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Div by 0 error caught!</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">i</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">{ . }</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">for-each</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<h2><code>error-safe-03.xsl</code></h2>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">my</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">my:error-safe-03.xsl</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ex</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:/org.fgeorges.exslt2.saxon.Exslt2InstructionFactory</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my xs</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">extension-element-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ex</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Test from Michael Kay, see http://sf.net/mailarchive/message.php?msg_id=37863852
Here the risk is that the evaluation is done lazily after exit
from the function, outside the range of the try/catch. Again, I
think this might work OK, but it needs careful checking. (If it
works, it's because the whole xsl:error-safe expression is being
lazily evaluated).
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:div(1 to 5, 0)</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ERROR</span> <span class="fl-nxml-attribute-local-name">what</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Div by 0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">where</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">In main!</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:div</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">n</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer*</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">param</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">d</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span> <span class="fl-nxml-attribute-prefix">saxon</span><span class="fl-nxml-attribute-colon">:</span><span class="fl-nxml-attribute-local-name">explain</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">for $i in $n return $i div $d</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">div-by-0</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">function</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>This test case failed. The error is caught on the <code>main</code> template, instead of within the <code>my:div()</code> function. I looked at the Saxon's internals deeper, but I am still lost with all rewriting, optimizing, simplifying, lazy evaluation, optimizing, etcetera. It is interesting to see that the expression trees, after optimization, are as follow:</p>
<pre class="drkm-code-div">
Optimized expression tree for template at line 23 in error-safe-03.xsl:
element
name root
content
error-safe
try
call my:div
operator to
1
5
0
catch
element
name ERROR
content
attribute
name what
"Div by 0"
attribute
name where
"In main!"
Optimized expression tree for function my:div at line 38 in error-safe-03.xsl:
error-safe
try
value-of
construct simple content
for $i as xs:integer in
$n
return
operator div
$i
$d
" "
catch
element
name div-by-0
content
()
</pre>
<p>I need more investigation (and I think more help) to see if that can be solved.</p>
<h2><code>error-safe-04.xsl</code></h2>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ex</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:/org.fgeorges.exslt2.saxon.Exslt2InstructionFactory</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">extension-element-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ex</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">omit-xml-declaration</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
Test from Michael Kay, see http://sf.net/mailarchive/message.php?msg_id=37863852
Here the risk is that the error won't be caught because the
expression is evaluated early, at compile time (the so-called
"constant folding" process).
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">call-template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ERROR</span> <span class="fl-nxml-attribute-local-name">what</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">Div by 0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">where</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">In main!</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">variable</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">zero</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">as</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs:integer</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">value-of</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1 div $zero</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">div-by-0</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<h2><code>error-safe-05.xsl</code></h2>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">my</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">my:error-safe-05.xsl</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ex</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:/org.fgeorges.exslt2.saxon.Exslt2InstructionFactory</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">xs</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">extension-element-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ex</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">omit-xml-declaration</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-comment-delimiter"><!--</span><span class="fl-nxml-comment-content">
The error occurs in the middle of an element construction. What
to do?
</span><span class="fl-nxml-comment-delimiter">--></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">error(xs:QName('my:ERROR'), 'Error')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">error</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">stylesheet</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>This test case shows in my opinion the worst problem. The problem is both technical and specification-related. The test case seems simple: an <code>ex:try</code> element contains as sequence constructor a unique literal element, that in turn contains a simple <code>xsl:sequence</code> instruction that throw an error. Something (more simple than) usual.</p>
<p>Usually, when an error is thrown, the transformation failed, stop brutaly, an the result is not serialized. But with <code>ex:error-safe</code>, the error is caught and the transformation continues. But the closing tag of the literal element within the error was thrown was never <em>seen</em>. So when the result "tree" is serialized, there is an error, because the sequence of events no longer represents a valid XML fragment.</p>
<p>So I need to define what to do in this case. Discard all the pending result of the sequence constructor already generated? <em>Close</em> every still <em>opened</em> nodes? Keep the items of the sequence but the last one if it is a node not fully build?</p>
<p>In the points of view of both the specification and the implementation, I am not sure what os the right thing to do.</p>
<p>To be continued...</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com0tag:blogger.com,1999:blog-33074681.post-1168304721077951212007-01-09T01:36:00.000+01:002007-01-12T06:57:14.250+01:00Try/catch in XSLT 2.0<p>I have experimented a little bit with Saxon B 8.8.0.4j to implement a try/catch instruction in XSLT. The overall idea is simple: an element <code>error-safe</code> (the name is maybe not very nice, but I didn't find anything else now) contains an element <code>try</code> then a suite of 1 or more elements <code>catch</code>. <code>try</code> and <code>catch</code> both contain any sequence constructor. <code>catch</code> has an optional <code>@errors</code> attribute that is a space-separated list of QNames, representing error names:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">any-sequence-constructor</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">catch</span> <span class="fl-nxml-attribute-local-name">errors</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">err:ERRNAME</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">any-sequence-constructor</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">any-sequence-constructor</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>These are just some tests, and there is still a lot of things to specify, but this first implementation is quite usable I think and was incredibly easy to write with Saxon 8.8. Thanks Mike (as well for your help today)! Below are the four Java files: <a href="http://www.fgeorges.org/purl/20070108/Exslt2InstructionFactory.java"><code>Exslt2InstructionFactory.java</code></a>, <a href="http://www.fgeorges.org/purl/20070108/ErrorSafe.java"><code>ErrorSafe.java</code></a>, <a href="http://www.fgeorges.org/purl/20070108/Try.java"><code>Try.java</code></a> and <a href="http://www.fgeorges.org/purl/20070108/Catch.java"><code>Catch.java</code></a>.</p>
<pre class="drkm-code-div">
<span class="fl-keyword">package</span> org.fgeorges.exslt2.<span class="fl-constant">saxon</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">style</span>.<span class="fl-type">ExtensionElementFactory</span>;
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">Exslt2InstructionFactory</span>
<span class="fl-keyword">implements</span> <span class="fl-type">ExtensionElementFactory</span>
{
<span class="fl-keyword">public</span> <span class="fl-type">Class</span> <span class="fl-function-name">getExtensionClass</span>(<span class="fl-type">String</span> <span class="fl-variable-name">localname</span>) {
<span class="fl-keyword">if</span> ( localname.equals(<span class="fl-string">"error-safe"</span>) ) {
<span class="fl-keyword">return</span> ErrorSafe.<span class="fl-keyword">class</span>;
}
<span class="fl-keyword">if</span> ( localname.equals(<span class="fl-string">"try"</span>) ) {
<span class="fl-keyword">return</span> Try.<span class="fl-keyword">class</span>;
}
<span class="fl-keyword">if</span> ( localname.equals(<span class="fl-string">"catch"</span>) ) {
<span class="fl-keyword">return</span> Catch.<span class="fl-keyword">class</span>;
}
<span class="fl-keyword">return</span> null;
}
}
</pre>
<pre class="drkm-code-div">
<span class="fl-keyword">package</span> org.fgeorges.exslt2.<span class="fl-constant">saxon</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">util</span>.<span class="fl-type">Map</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">util</span>.<span class="fl-type">HashMap</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">Expression</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">SimpleExpression</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">XPathContext</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">instruct</span>.<span class="fl-type">Executable</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">Axis</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">AxisIterator</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">NodeInfo</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">style</span>.<span class="fl-type">ExtensionInstruction</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">DynamicError</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">XPathException</span>;
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">ErrorSafe</span>
<span class="fl-keyword">extends</span> <span class="fl-type">ExtensionInstruction</span>
{
<span class="fl-keyword">public</span> <span class="fl-type">Expression</span> <span class="fl-function-name">compile</span>(<span class="fl-type">Executable</span> <span class="fl-variable-name">exec</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
Map<String, Catch> handlers = <span class="fl-keyword">new</span> <span class="fl-type">HashMap</span><String, Catch>();
<span class="fl-type">AxisIterator</span> <span class="fl-variable-name">kids</span> = iterateAxis(<span class="fl-constant">Axis</span>.CHILD);
<span class="fl-type">Expression</span> <span class="fl-variable-name">tryExpr</span> = null;
<span class="fl-keyword">while</span> ( true ) {
<span class="fl-type">NodeInfo</span> <span class="fl-variable-name">curr</span> = (<span class="fl-type">NodeInfo</span>) kids.next();
<span class="fl-keyword">if</span> (curr == null) {
<span class="fl-keyword">break</span>;
}
<span class="fl-keyword">else</span> <span class="fl-keyword">if</span> ( curr <span class="fl-keyword">instanceof</span> Try ) {
tryExpr = ((<span class="fl-type">Try</span>) curr).compile(exec);
}
<span class="fl-keyword">else</span> <span class="fl-keyword">if</span> ( curr <span class="fl-keyword">instanceof</span> Catch ) {
<span class="fl-type">Catch</span> <span class="fl-variable-name">c</span> = (<span class="fl-type">Catch</span>) curr;
<span class="fl-type">String</span>[] <span class="fl-variable-name">errors</span> = c.getErrors();
<span class="fl-keyword">if</span> ( null == errors ) {
handlers.put(null, c);
}
<span class="fl-keyword">else</span> {
<span class="fl-keyword">for</span> ( <span class="fl-type">int</span> <span class="fl-variable-name">i</span> = 0; i < errors.length; ++i ) {
handlers.put(errors[i], c);
}
}
c.compile(exec);
}
<span class="fl-keyword">else</span> {
<span class="fl-comment-delimiter">// </span><span class="fl-comment">TODO: Report a compilation error!
</span> }
}
<span class="fl-keyword">return</span> <span class="fl-keyword">new</span> <span class="fl-type">ErrorSafeExpression</span>(tryExpr, handlers);
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">prepareAttributes</span>() {
}
}
<span class="fl-keyword">class</span> <span class="fl-type">ErrorSafeExpression</span>
<span class="fl-keyword">extends</span> <span class="fl-type">SimpleExpression</span>
{
<span class="fl-keyword">public</span> ErrorSafeExpression(<span class="fl-type">Expression</span> <span class="fl-variable-name">expr</span>, Map<String, Catch> handlers) {
myTry = expr;
myHandlers = handlers;
myDefaultHandler = handlers.get(null);
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">process</span>(<span class="fl-type">XPathContext</span> <span class="fl-variable-name">ctxt</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
<span class="fl-keyword">try</span> {
myTry.process(ctxt);
}
<span class="fl-keyword">catch</span> ( <span class="fl-type">DynamicError</span> <span class="fl-variable-name">err</span> ) {
<span class="fl-type">String</span> <span class="fl-variable-name">error</span> = <span class="fl-string">'{'</span> + err.getErrorCodeNamespace() + <span class="fl-string">'}'</span> + err.getErrorCodeLocalPart();
<span class="fl-type">Catch</span> <span class="fl-variable-name">handler</span> = myHandlers.get(error);
<span class="fl-keyword">if</span> ( handler != null ) {
handler.handle(err, ctxt);
}
<span class="fl-keyword">else</span> <span class="fl-keyword">if</span> ( null != myDefaultHandler ) {
myDefaultHandler.handle(err, ctxt);
}
<span class="fl-keyword">else</span> {
<span class="fl-keyword">throw</span> err;
}
}
}
<span class="fl-keyword">private</span> <span class="fl-type">Expression</span> <span class="fl-variable-name">myTry</span> = null;
<span class="fl-keyword">private</span> <span class="fl-type">Catch</span> <span class="fl-variable-name">myDefaultHandler</span> = null;
<span class="fl-keyword">private</span> <span class="fl-type">Map</span><String, Catch> myHandlers = null;
}
</pre>
<pre class="drkm-code-div">
<span class="fl-keyword">package</span> org.fgeorges.exslt2.<span class="fl-constant">saxon</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">Expression</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">instruct</span>.<span class="fl-type">Executable</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">Axis</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">style</span>.<span class="fl-type">ExtensionInstruction</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">XPathException</span>;
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">Try</span>
<span class="fl-keyword">extends</span> <span class="fl-type">ExtensionInstruction</span>
{
<span class="fl-keyword">public</span> <span class="fl-type">Expression</span> <span class="fl-function-name">compile</span>(<span class="fl-type">Executable</span> <span class="fl-variable-name">exec</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
<span class="fl-keyword">return</span> compileSequenceConstructor(exec, iterateAxis(<span class="fl-constant">Axis</span>.CHILD), true);
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">prepareAttributes</span>() {
}
}
</pre>
<pre class="drkm-code-div">
<span class="fl-keyword">package</span> org.fgeorges.exslt2.<span class="fl-constant">saxon</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">java</span>.<span class="fl-constant">util</span>.<span class="fl-type">ArrayList</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">Expression</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">SimpleExpression</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">expr</span>.<span class="fl-type">XPathContext</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">instruct</span>.<span class="fl-type">Executable</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">Axis</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">om</span>.<span class="fl-type">AttributeCollection</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">style</span>.<span class="fl-type">ExtensionInstruction</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">DynamicError</span>;
<span class="fl-keyword">import</span> <span class="fl-constant">net</span>.<span class="fl-constant">sf</span>.<span class="fl-constant">saxon</span>.<span class="fl-constant">trans</span>.<span class="fl-type">XPathException</span>;
<span class="fl-keyword">public</span> <span class="fl-keyword">class</span> <span class="fl-type">Catch</span>
<span class="fl-keyword">extends</span> <span class="fl-type">ExtensionInstruction</span>
{
<span class="fl-keyword">public</span> <span class="fl-type">Expression</span> <span class="fl-function-name">compile</span>(<span class="fl-type">Executable</span> <span class="fl-variable-name">exec</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
myAction = compileSequenceConstructor(exec, iterateAxis(<span class="fl-constant">Axis</span>.CHILD), true);
<span class="fl-keyword">return</span> myAction;
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">prepareAttributes</span>()
<span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
<span class="fl-type">String</span> <span class="fl-variable-name">errors</span> = null;
<span class="fl-type">AttributeCollection</span> <span class="fl-variable-name">atts</span> = getAttributeList();
<span class="fl-keyword">for</span> ( <span class="fl-type">int</span> <span class="fl-variable-name">a</span> = 0; a < atts.getLength(); ++a ) {
<span class="fl-keyword">if</span> ( <span class="fl-string">""</span>.equals(atts.getPrefix(a)) && <span class="fl-string">"errors"</span>.equals(atts.getLocalName(a)) ) {
errors = atts.getValue(a);
<span class="fl-keyword">break</span>;
}
}
<span class="fl-keyword">if</span> ( errors != null ) {
<span class="fl-type">String</span>[] <span class="fl-variable-name">qnames</span> = errors.split(<span class="fl-string">" +"</span>);
myErrors = <span class="fl-keyword">new</span> <span class="fl-type">String</span>[qnames.length];
<span class="fl-keyword">for</span> ( <span class="fl-type">int</span> <span class="fl-variable-name">i</span> = qnames.length; i > 0; --i ) {
<span class="fl-type">String</span> <span class="fl-variable-name">qn</span> = qnames[i - 1];
<span class="fl-keyword">if</span> ( <span class="fl-negation-char">!</span> <span class="fl-string">""</span>.equals(qn) ) {
<span class="fl-type">int</span> <span class="fl-variable-name">colons</span> = qn.indexOf(<span class="fl-string">':'</span>);
<span class="fl-type">String</span> <span class="fl-variable-name">prefix</span> = qn.substring(0, colons);
<span class="fl-type">String</span> <span class="fl-variable-name">local</span> = qn.substring(colons + 1);
myErrors[i - 1] =
<span class="fl-string">'{'</span> + getNamespaceResolver().getURIForPrefix(prefix, false) + <span class="fl-string">'}'</span> + local;
}
}
}
}
<span class="fl-keyword">public</span> <span class="fl-type">String</span>[] <span class="fl-function-name">getErrors</span>() {
<span class="fl-keyword">return</span> myErrors;
}
<span class="fl-keyword">public</span> <span class="fl-type">void</span> <span class="fl-function-name">handle</span>(<span class="fl-type">DynamicError</span> <span class="fl-variable-name">err</span>, <span class="fl-type">XPathContext</span> <span class="fl-variable-name">ctxt</span>)
<span class="fl-keyword">throws</span> <span class="fl-type">XPathException</span>
{
myAction.process(ctxt);
}
<span class="fl-keyword">private</span> <span class="fl-type">String</span>[] <span class="fl-variable-name">myErrors</span> = null;
<span class="fl-keyword">private</span> <span class="fl-type">Expression</span> <span class="fl-variable-name">myAction</span> = null;
}
</pre>
<p>Here is an simple complete example in XSLT using the above classes, <a href="http://www.fgeorges.org/purl/20070108/error-safe.xsl"><code>error-safe.xsl:</code></a></p>
<pre class="drkm-code-div">
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">transform</span> <span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xsl</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/1999/XSL/Transform</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">err</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2005/xqt-errors</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">xs</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">http://www.w3.org/2001/XMLSchema</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">ex</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">java:/org.fgeorges.exslt2.saxon.Exslt2InstructionFactory</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-namespace-attribute-xmlns">xmlns</span><span class="fl-nxml-namespace-attribute-colon">:</span><span class="fl-nxml-namespace-attribute-prefix">my</span>=<span class="fl-nxml-namespace-attribute-value-delimiter">"</span><span class="fl-nxml-namespace-attribute-value">my:error-safe.xsl</span><span class="fl-nxml-namespace-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">exclude-result-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">err my xs</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">extension-element-prefixes</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">ex</span><span class="fl-nxml-attribute-value-delimiter">"</span>
<span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">2.0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">output</span> <span class="fl-nxml-attribute-local-name">indent</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">yes</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">main</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">first</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">call-template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">first-test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">first</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">second</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">call-template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">second-test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">second</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">first-test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1 div 0</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ok</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span> <span class="fl-nxml-attribute-local-name">errors</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">err:FOAR0001</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">div-by-0</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span> <span class="fl-nxml-attribute-local-name">name</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">second-test</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">sequence</span> <span class="fl-nxml-attribute-local-name">select</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">error(xs:QName('my:err0001'), 'Error message!')</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">ok</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">try</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span> <span class="fl-nxml-attribute-local-name">errors</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:err0001 my:err0003</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">handle-1</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span> <span class="fl-nxml-attribute-local-name">errors</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">my:err0002</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">handle-2</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">handle-all</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">catch</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">ex</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">error-safe</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">template</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-prefix">xsl</span><span class="fl-nxml-element-colon">:</span><span class="fl-nxml-element-local-name">transform</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Run with the right incantation, for example the following, with the script described <a href="http://fgeorges.blogspot.com/2007/01/shell-script-to-launch-saxon.html">here</a>: <code>saxon --b --add-cp=fgeorges.jar -it main error-safe.xsl</code> (if the classes are compiled in <code>fgeorges.jar</code>), this produces:</p>
<pre class="drkm-code-div">
<span class="fl-nxml-processing-instruction-delimiter"><?</span><span class="fl-nxml-processing-instruction-target">xml</span> <span class="fl-nxml-attribute-local-name">version</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">1.0</span><span class="fl-nxml-attribute-value-delimiter">"</span> <span class="fl-nxml-attribute-local-name">encoding</span>=<span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-attribute-value">UTF-8</span><span class="fl-nxml-attribute-value-delimiter">"</span><span class="fl-nxml-processing-instruction-delimiter">?></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">first</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">div-by-0</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">first</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">second</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-element-local-name">handle-1</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">second</span><span class="fl-nxml-tag-delimiter">></span>
<span class="fl-nxml-tag-delimiter"><</span><span class="fl-nxml-tag-slash">/</span><span class="fl-nxml-element-local-name">root</span><span class="fl-nxml-tag-delimiter">></span>
</pre>
<p>Extension functions could now be added to provide the name and message of the currently trapped error within a <code>catch</code> element.</p>Florent Georgeshttp://www.blogger.com/profile/18018229770454570703noreply@blogger.com2