Interactive XSLT in the browser
Copyright © 2013 by the authors. Used with permission.
Table of Contents
However, as successful as HTML as been to the browser, there exists an underlying problem, in that HTML is not best suited to representing document data. Such data we would expect to be stored on web servers or close to the browser on the client machine. XML was created to solve this problem, as a multi-purpose and platform-neutral text-base meta language, which could be used for storage, transmission and manipulation of data. It was a great way to represent data, but the question was what could we do with it on the browser? Given the introduction of XHTML as an application of XML with HTML, direct rendering of XML was not possible as browsers were designed for use with HTML. The need of program application to convert these special data documents written in XML to HTML became paramount.
The answer to this was XSLT. It was designed as a functional programming language for XML. It was now possible to convert XML documents into HTML documents which in turn could be rendered in the browsers. This was great for the 'Web 1.0' architecture, where we have static documents on the web, which needed to be rendered in the browser.
XSLT 1.0 was published in 1999 XSLT20. On the server it presented a way to convert XML data into HTML before it reached the browser. But the challenge was to get XSLT closer to the browser. Before the specification was finished Microsoft implemented XSLT 1.0 as an add-on to Internet Explorer (IE) 4, which became an integral part of IE5. (Microsoft made a false start by implementing a draft of the W3C specification that proved significantly different from the final Recommendation, which didn't help.) It then took a long time before XSLT processors with a sufficient level of conformance and performance were available across all common browsers. In the first couple of years the problem was old browsers that didn't have XSLT support; then the problem became new browsers that didn't have XSLT support. In the heady days while Firefox market share was growing exponentially, its XSLT support was very weak. More recently, some mobile browsers have appeared on the scene with similar problems. So there has never been a time when good XSLT 1.0 support was universal
By the time XSLT 1.0 conformance across browsers was substiantially achieved (say around 2009, if we exclude old browsers and newer mobile devices), other technologies had changed the goals for browser vendors. The emergence of XSLT 2.0 XSLT20, which made big strides over XSLT 1.0 in terms of developer productivity, never attracted any enthusiasm from the browser vendors — and the browser platforms were sufficiently closed that there appeared to be little scope for third-party implementations.
Because the Saxon XSLT 2.0 processor is written in Java, this gave us the opportunity to create a browser-based XSLT 2.0 processor by cutting down Saxon to its essentials and cross-compiling using GWT. An inspiration that such a project was possible was the development of the XProc engine for the browser vojt2010, as it was implemented using GWT.
The first implementation of XSLT 2.0 for the browser we call Saxon-CE SAXONCE. In this short paper we investigate the underlying concepts of Saxon-CE. Specifically, how does one use XSLT 2.0, which is a purely functional language to manipulate a stateful interactive dialogue with the user to develop web applications.
XSLT as a declarative language was influenced by the ideas of functional programming, and by text-based pattern matching lnaguages. In essence, we have an input document, ideally written in XML, which would then go into the XSLT process and then produce output at the other end. The output would be some result document in a desired format, which would be in many cases XML, HTML or some other textual representation. The template rule structure of the XSLT stylesheet made it posssible to match XML documents and their sub-trees in a recursive rule-based process while generating the output.
Offering XSLT 2.0 in the browser is a benefit to those coding XSLT 1.0 in the web, as it presents many advances, in term of extra capability and productivity. Regular expression support, user-written functions, and grouping are the most obvious examples, familiar to anyone at this conference. But offering interaction via XSLT 2.0 in the browser allows us to start winning over those Web 2.0 developers in supporting interaction and event handling.
In Saxon-CE we have a true XSLT 2.0 processor for the browser with some key extensions. However, what is different from our traditional approach when developing in XSLT is what we consider as our input and output document. The input not only can be some text-based document, as in XML, but we have available the HTML DOM tree from the browser in the current instance of the web page loaded. This is important when we think of accessing the HTML as we see it on the browser. Likewise the output would typically be to the HTML DOM. The output in fact is typically some document fragment which can be attached to the HTML tree, ready for the next phase of processing, as discussed later in this paper.
The following features are standard in XSLT 2.0, but we extend their use to support interaction, either through language extensions or through an imaginative interpretation of the flexibility that the language specification gives to implementors:
Multiple result files: The instruction
XSLT 2.0 allow us to create multiple result trees. In Saxon-CE we take advantage
of this instruction in an innovative way: we allow the transformation to create
many small sub-trees, each of which is written to a different part of the HTML
page. This means that a transformation phase does not need to rewrite the whole
HTML document, it only needs to write those parts that have changed as a result
of the user interaction. This leads to a radically different programming
approach from the way XSLT is conventionally used. The
xsl:result-document instruction uses a URI to define the
destination of the result tree; Saxon-CE defines a URI syntax that allows
addressing into the HTML document, so that the result tree can be written to any
part of the page
Similarly, Saxon-CE also extends the XDM model to provide access to information beyond the scope of the HTML DOM, such as the properties of the browser window itself.
Template rules with mode setting: XSLT 2.0 allows a transformation to be
initiated with a given context node, in a given mode. Saxon-CE takes advantage
of this to process user interaction events in the browser, such as the user
clicking a button. When an on-click event occurs on a button object, a
transformation is initiated with the HTML element representing the button as the
initial context node, and with the initial mode
ixsl is a Saxon-CE defined namespace). Each such event
starts a new transformation, which can produce one or more result trees. To
preserve the purely functional semantics of XSLT, these result trees are not
written back to the HTML DOM until the transformation has finished; a
transformation cannot see its own updates. The approach used to achieve this is
very similar to the use of pending update lists in XQuery Update (in fact the
code is directly lifted from Saxon's implementation of XQuery updates). A
beneficial effect of this has been high reliability; the product is largely
insulated from the concurrency effects that otherwise occur when many events
occur in quick succession, each modifying the same shared data.
As well as handling user interaction events, Saxon-CE also allows a transformation to be triggered by a timer event, thus enabling animations.
Use of XSLT functions: XSLT 2.0 allows and encourages the development of
function libraries by vendors and third parties, rather than requiring
everything to be in the core language. Saxon-CE fully takes advantage of this
flexibility and extensibility. Built in to the product is a small library of
essential functions needed by anyone developing browser-based applications.
These fall into two groups. The first group contains functions which access
parts of the browser environment (
ixsl:page gets the HTML document,
ixsl:source gets the XML source document,
ixsl:window gets the browser window,
gets the current event). The second group provides interoperability between XSLT
In Figure 1 we illustrate that with Saxon-CE we can
manipulate the HTML DOM tree and handle events with the use of
The code snippet below gives further detail of the use of the
xsl:result-document instruction. The
contains a '#' symbol followed by the
id value referencing the element
in the HTML DOM tree. This is where we would like to make modifications in the DOM
tree, for example we use the
id attribute of the
method attribute has the value 'append-content' which
causes the result tree to be written as the last child of the
element. Using the alternative 'replace-content' causes all its child nodes to be
<xsl:result-document href="#x" method="append-content"> <p>text1</p> </xsl:result-document>
As discussed before, in Saxon-CE we take advantage of modes in template instructions
to handle events which match the rule in the match attribute. This we show in the
code snippet below. Here we use the function
matches with an regular
expression when matching a
div element. We also show how we can set the
<xsl:template match="div[matches(@id, '\w\d')]" mode="ixsl:onclick"> <xsl:variable name="initial-square" select="@id"/> <ixsl:set-property name="value" object="ixsl:page()//input[@id='inputBx']" select="concat($initial-square, '-')"/> </xsl:template>
Figure 1: HTML DOM Tree
GWT does not offer the full range of class libraries available on the standard Java-SE
but it provides 90% of the interfaces that Saxon needs. Filling the gaps was not difficult.
Some of the
gaps are a little surprising, for example there is no
java.net.URI class; but there
are plenty of open-source alternatives that provide the functionality Saxon uses.
maps Java's integer
and long types to double-precision floating point. In view of this, we decided in
Saxon to implement the
xs:decimal data types using the Java
BigDecimal class, which is available
in GWT and appears to perform quite adequately.
The Saxon-EE product is over 250,000 lines of code. Key to Saxon-CE performance is
the size of the code
that needs to be downloaded, and so an early imperative was to cut this down. There
was no shortage of opportunities:
the schema processor and the query processor were obvious candidates. Less obvious
was the decision to drop the
TinyTree implementation of the XDM model, and rely on the much slower DOM. The final
this results in a visible
delay when starting a Saxon-CE application, typically a couple of seconds — not a
long enough delay to deter most users.
And of course the code is cached, so this happens only on first access. There is scope
to reduce the code size
more than this — aggressive pruning could probably bring it down to half this, but
there is a law of diminishing
returns. Some of the bulkier parts of the code are already paged in on demand (for
example the data tables needed
to support Unicode normalization) and this technique could be extended.
Key to the practical utility of the product is the availability of developer tools. Hopefully in time third-party vendors will see the benefits of adding to the tooling available, but the product already comes with a very useful starter set of capabilities for tracing and debugging, fully integrated with the browser's developer console.
The application we will demonstrate at the conference is perhaps one area where the benefits of XSLT in the browser are easiest to appreciate. It is also a live production application SAXONDOC. Both the "mainstream" Saxon and the Saxon-CE documentation are now delivered using this application, which provides an interactive browser/reader for the technical documentation.
There's a catalog file on the server containing a top-level table of contents, which enables the contents menu to be displayed without downloading all 20 files; the rest of the content is downloaded on demand. It's a single page application, which presents a page-oriented hyperlinked view of the documentation in which each page has its own "hash-bang" URI which can be written down, bookmarked, and exchanged by email: all navigation functions within the application update this URI in the browser window, so the back button works as expected and generally, the experience of regular web browsing is faithfully reproduced, but with much better responsiveness.
The benefits of the approach are particularly noticeable for the Javadoc API browser. Saxon is a big product and the static Javadoc was becoming extremely unwieldy, as well as delivering a very old-fashioned image. The sheer bulk of the HTML files (each containing reams of identical presentation information, as well as highly redundant content) made it difficult to manage, discouraging incremental updates and corrections, or maintenance of multiple versions. For the new approach, we found and adapted a Javadoc plug-in (or "doclet") to generate XML instead of HTML, and then do a modest amount of server-side XSLT processing on this XML prior to publication; the rest of the job is done by the XSLT 2.0 stylesheet on the browser. The result for the user is much slicker navigation around the information; for the publisher (ourselves) it's a much lighter-weight publication workflow.
[XSLT10] Clark, James. XSL Transformations (XSLT) Version 1.0, 16 November 1999. W3C Recommendation. http://www.w3.org/TR/xslt
[vojt2010] Vojtěch, Toman. XML Pipeline Processing in the Browser. Presented at Balisage: The Markup Conference 2010, Montréal, Canada, August 3 - 6, 2010. In Proceedings of Balisage: The Markup Conference 2010. Balisage Series on Markup Technologies, vol. 5 (2010). doi:https://doi.org/10.4242/BalisageVol5.Toman01.
[SAXONDEMO] Saxon-CE Demonstrations. Saxonica. http://www.saxonica.com/ce/user-doc/1.1/index.html#!demonstrations