Erik A. Hanson's Weblog

How To Use Google’s Ajaxslt Library

Posted: September 30th, 2005    Tags: Howto, Javascript, XSL

Google has written an open-source library called Ajaxslt that implements XPath and XSLT in Javascript.

It took a bit of playing to get it to work. Here’s some sample code. (I forgot to write it up when I did it, so I might have left something out.)

Setup

First, include the scripts. Note: make sure to have a closing </script> tag rather than doing <script … /> because that silently fails on some browsers (yay!).

<!-- AJAXSLT -->
<script src="/ajaxslt/misc.js"
    type="text/javascript"></script>

<script src="/ajaxslt/dom.js"
    type="text/javascript"></script>

<script src="/ajaxslt/xpath.js"
    type="text/javascript"></script>

<script src="/ajaxslt/xslt.js"
    type="text/javascript"></script>

<script src="/ajaxslt/xpathdebug.js"
    type="text/javascript"></script>

Using Ajaxslt for XSL Transformation

For XSL transformation, you’ll need three things: some XML, some XSL, and a node (or DocumentFragment presumably) to place the result in. One way to get the XML and XSL is to load them through an XmlHttpRequest. Ajaxslt also provides a couple of handy functions to convert between text and XML:

var myText = "...";
var myXml = xmlParse(myText);
var myTextAgain = xmlText(myXml);

Once you’ve got the XML and XSL, you’re ready to do the transformation:

var myNode = document.getElementById("myId");
xsltProcessContext(new ExprContext(myXml), myXsl, myNode);

Your node should now contain the result of the transformation.

Using Ajaxslt for XPath

You can also use Ajaxslt for XPath evaluation, which is really handy when writing tests on your rendered document:

var expr = xpathParse(myXpathString);
var result = expr.evaluate(new ExprContext(myXmlDocument));
var resultAsString = result.stringValue();

Troublshooting

The order of the JavaScript include statements matters: if Ajaxslt is giving strange errors, make sure the scripts are included in the exact same order as in the Setup section of this page.

Make sure you know what you’re passing to Ajaxslt: if you’re sending request.responseXML to a method, don’t look at request.responseText to see what you’re passing; use xmlText(request.responseXML).

The root element isn’t selectable: if your XML is <foo id="myId">…</foo>, then you don’t select foo’s id with /foo/@id but rather with just @id.

Case matters in xpath: If you’re evaluating an xpath expression on an HTML DOM, note that the node names are most likely uppercase. So do /HTML/BODY instead of /html/body



27 Responses to “How To Use Google’s Ajaxslt Library”

  1. MLGrant Says:

    Erik,

    Just wanted to say thank you for this (and your other) How To, this is just what I need to get a foot in the door with Ajaxslt! It’s really hard to know where to start in order to get a handle on this technology as it evolves so it helps to simplify things like this.

    Regards,
    MLGrant

  2. Erik Says:

    You’re welcome. A little while ago, I decided that if I ever struggled with something techincal, I’d write up a howto and put it online in the hopes that it would save someone a little time. I’m glad that it’s helped at least one person…

  3. neil Says:

    I just found this while randomly browsing and having seen the above 2 comments I thought I would add my own thankyou. I am just looking into setting up my own ajax/ruby etc project (after years of assorted everything else) and this site is a great help and a great example to me to do the same kind of technical documentation.

    Cheers
    Neil

  4. Gary Says:

    Hi Erik,

    thank you very much for your tutorial. It helps me to understand Google AJAXSLT better. I have a question though, and I hope u can / would help me solve the problem.

    In your tutorial, it seems that the XML & XSL are put in a text form in the code. I’d like to use AJAXSLT to import an external XML & XSL file, perform the transformation, and generate an text xml-output. Is it possible to perfrom this task using AJAXSLT?

    Thank you very much in advance,

    Gary

  5. Erik Says:

    Hi Gary,

    I use the Ajaxslt library to do exactly what you are asking about.

    My HTML page and Javascript load and put up a “Loading…” message. Then the Javascript makes an XmlHttpRequest for some XML and another XmlHttpRequest for some XSL. When both have arrived, I get the XML and XSL from the XmlHttpRequests (using the XmlHttpRequest’s “responseXML” field) and have Ajaxslt render them.

    So something like:

    xsltProcessContext(new ExprContext(myXmlRequest.responseXML), myXslRequest.responseXML, myNode);

    Apple has a good tutorial on XmlHttpRequest: http://developer.apple.com/internet/webcontent/xmlhttpreq.html

    Also, the Prototype library has an XmlHttpRequest wrapper (but not much documentation): http://prototype.conio.net/

    And don’t forget about the Ajaxslt list: http://groups.google.com/group/google-ajax-discuss

  6. Anh Khoa Huynh Says:

    First of all, i want to say thanks to you.

    At the page http://www.ubivn.com/xichlo/?m=ajax&a=tutorial1 , i follow your tutorial. After clicking on the “Get XML” and “Get XSLT” button to fetch 2 file tutorial1.xml and tutorial1.xsl, i click on the “Get Result” then I get the message at the top-right of the screen. Did I do something wrong in my source code ?

    Thanks in advance,

    ANH KHOA HUYNH

  7. Erik Says:

    The message at the top-right is some Ajaxslt debugging info, which I seem to remember is enabled by default. I forget right now how to disable it, but it shouldn’t be too hard.

    Your code looks fine upon quick inspection. If you’re sure that you’re getting the XML and XSL back correctly (which you can inspect with the xmlText() function described above), then it might be a matter of the XSL not matching any elements in the XML so you might need to fiddle with the XSL a bit.

  8. Anh Khoa Huynh Says:

    Hi Erik

    I follow your reply and get the result successfully. But it seems that the result is appended to the ABC text which is available before. So what should i do to replace ABC text with the result instead of appending ?

    Thanks a lot Erik,
    ANH KHOA HUYNH

  9. Erik Says:

    I forgot to mention it in my short tutorial, but as you have discovered, Ajaxslt appends its result to the node you pass in.

    One way to get around it is to remove all the child nodes of the target node before calling xsltProcessContext().

    Another way would be to create a new node (perhaps a div), pass that into xsltProcessContext(), and tell your target node’s parent to replace the target node with the new node that you created (something like: targetNode.parentNode.replaceChild(newNode, targetNode) )

  10. Craig Says:

    hi, I am a newbie to this AJAX and SLT and XPATH stuff so please ignore my ignorance!

    I’ve been reading docs on ajax and they all seem to talk about this XML request. Where is the server for this request located? I have a web server running apache, and I have some perl cgi’s that query MySQL to retrieve information from users. Do I need to add another module on my machine (server side) to handle the XML requests that AJAX sends? Please clarify!

  11. Erik Says:

    The XMLHttpRequest is part of Javascript and therefore lives in the browser, not on the server. The server just has to respond to regular HTTP requests, usually by sending XML though it’s not necessary.

    For example, your Javascript might make an XMLHttpRequest for http://www.example.com/cgi-bin/foo.pl which would then return some XML for the Javascript to process.

    You can read more about XMLHttpRequest here: http://developer.apple.com/internet/webcontent/xmlhttpreq.html

  12. Benson Margulies Says:

    Firefox’s builtin DOM doesn’t work with this XPath. It constantly encounters permission errors.

    Continuing from thrown exception.
    Exception “Permission denied to get property XMLDocument.firstChild” thrown from function xpathCollectDescendants(nodelist=Array:{2}, node=XMLDocument:{0}) in line 2094.
    Stopped for thrown exception.

    Furthermore, IE and Firefox disagree on their handling of namespace prefixes. IE leaves them in the names of nodes, Firefox removes them.

    This can all be ducked by using the DOM parser that comes in the package, but it is very, very, slow in IE6. So, it looks like one would use the native DOM on IE and the google DOM on Firefox. Hmm.

  13. tmn Says:

    Does anyone see anything wrong with the following? I’m trying to use the XMLHttpRequest load xml and xslt documents like in the example above. Nothing is rendering though, the screen just remains blank. I tried xmlText(myXmlRequest.responseXML); and it returns empty.

    function transformXML()
    {
    var myXmlRequest = new ActiveXObject(”Microsoft.XMLHTTP”);
    var myXslRequest = new ActiveXObject(”Microsoft.XMLHTTP”);

    myXmlRequest.onreadystatechange = processReqChange;
    myXmlRequest.open(”GET”, “table0.xml”, true);
    myXmlRequest.send();

    myXslRequest.onreadystatechange = processReqChange;
    myXslRequest.open(”GET”, “table0.xslt”, true);
    myXslRequest.send();

    xmlText(myXmlRequest.responseXML);
    var myNode = document.getElementById(”htmldisplay”);
    xsltProcessContext(new ExprContext(myXmlRequest.responseXML), myXslRequest.responseXML, myNode);
    }

    thanks!

  14. Erik Says:

    The XMLHttpRequests are asyncronous by default, so the results are probably not coming back by the time the xstlProcessContext method is called. Try making the requests synchronous (by sending “false” as the last parameter to the request.open() methods), or move the last 4 lines of code into the processReqChange method.

  15. Jin Says:

    I used the xPath example above, but it took me a little while to figure out how to iterate over the resulting node-set, so I’m posting it here.

    var expr = xpathParse(xPath);
    var nodeSet = expr.evaluate(new ExprContext(this));
    //this returns a “node-set” object which must be converted to an array of nodes
    var nodeArr = nodeSet.nodeSetValue();

    //now you can use the array of nodes to iterate

    for(var i=0; i

  16. phil Says:

    I hope you can help…

    i thought the following would display my xml pge through my xsl page, however all i get is a grey box in top right corner with parse details.

    I click on link ro run “runNow()” function whicin turn runs requesXML & requestXSL (same as requesXML but not getting root_node. then onto the xsltprocess context

    i would appreciate any help,
    thanks

    var http_requestXML = false;
    var http_requestXSL = false;
    var xmldoc = false;
    var xsldoc = false;
    var root_node = false;

    function requestXML(url) {
    http_requestXML = false;
    if (window.XMLHttpRequest) { // Mozilla, Safari,…
    http_requestXML = new XMLHttpRequest();
    if (http_requestXML.overrideMimeType) {
    http_requestXML.overrideMimeType(’text/xml’);
    }
    } else if (window.ActiveXObject) { // IE
    try {
    http_requestXML = new ActiveXObject(”Msxml2.XMLHTTP”);
    } catch (e) {
    try {
    http_requestXML = new ActiveXObject(”Microsoft.XMLHTTP”);
    } catch (e) {}
    }
    }

    if (!http_requestXML) {
    alert(’Giving up :( Cannot create an XMLHTTP instance’);
    return false;
    }
    http_requestXML.onreadystatechange = getXML;
    http_requestXML.open(’GET’, url, true);
    http_requestXML.send(null);

    }

    function getXML() {
    if (http_requestXML.readyState == 4) {
    if (http_requestXML.status == 200) {
    xmldoc = http_requestXML.responseXML;
    alert(’gotXMLDoc.’);
    var root_node = xmldoc.getElementsByTagName(’root’);
    alert(’got root_node.’);
    } else {
    alert(’There was a problem with the request.’);
    }
    }
    }

    function runNow() {
    requestXML(’test.xml’);
    requestXSL(’test.xsl’);
    xsltProcessContext(new ExprContext(http_requestXML.responseXML), http_requestXSL.responseXML, root_node);
    }

  17. Erik Says:

    The third parameter to xsltProcessContext needs to be a node that already exists on your page — that is, it’s the node on your page that the result of the XML+XSL is rendered into. (You could use the “body” node or an empty div, for example.)

  18. phil Says:

    thanks, erik, I am away now =), however how do you turn the debugging off.
    kind regards

  19. Erik Says:

    Excellent. To turn off debugging, I think all you have to do is set the global variables “xsltdebug” and “xpathdebug” to false.

  20. phil Says:

    Thnks again for the pointer. It was actually logging. I found the global var in the misc.js file.
    I’ve left it as true for the mean time and have alteredit as a local variable in my script I am running, a la

    var logging__ = false;

    all the best,
    Phil

  21. Tito Says:

    HI,

    Any idea, why in the xsltProcessContext (… IE crashes and it get closed…
    If I comment that line, nothing happens…

    var html = xsltProcess(xmlData,xslData);
    var li=document.createElement(”div”);
    li.setAttribute(”id”, “result2″);
    xsltProcessContext(new ExprContext(xmlData),xslData, li); ### ANY IDEA WHY IN IE CRASH HERE ???
    var nd = document.getElementById(”result”);
    var parentDiv = nd.parentNode;
    parentDiv.replaceChild(li, nd);
    li.setAttribute(”id”, “result”);

    Thanks,
    Tito

  22. Erik Says:

    I haven’t used this library in a while so I can’t remember the things that make it crash. You could try debugging it. I don’t know much about debugging in IE, but if you can get it to crash in Firefox you could try installing the Firebug extension and using its debugger.

  23. Tito Says:

    I already have installed firebug… but the problem is that in Firefox works nice… but in IE crashes and close the window… requesting to “Send error”

  24. sameer Says:

    Hey I need some help regarding this…

    i need to show a page similar to a customized calender
    where I have a 8*8 table and all the cell will have background color according to the xml data which has a date field

    So if the date have specific data (in xml) I will color out the cell with specific color for that date.

    My problem is in implementing date addition in xslt. I dont know how to solve this may be we can add a javascript function and get its output in xslt ?

    Thanks
    -sameer

  25. Erik Says:

    If you really can’t do date addition in XSLT (I’ve never tried), you could always draw the table with XSLT and then color it later with Javascript.

    Though a quick Gooooooooogle search finds this page on XSLT date addition: http://www.dpawson.co.uk/xsl/rev2/dates.html

  26. Ettiene Says:

    Hi guys,

    Just want to say thanks to all of you for your comments and insight.

    I’ve got an xml file with a couple of main nodes (just below root) that I needed to separate and parse them 1 by 1 with an xsl file that contains templates for all of them, into HTML code. Then I’d write out that HTML string to a DIV on one of my webpages. Struggled for 2 days until I stumbled across this site. :)

    I basically used Prototype’s XMLHttpRequest implementation together with Sarissa’s XSLTProcessor functions to get it working. And it works on IE and FF! :)

    There’s just one problem, in IE my first click does nothing. I basically need to click on my button twice before it starts executing. On FF it works like a charm.

    Thanks
    Ettiene

  27. jmike Says:

    I am trying to make this work:

    var xml, xsl, menuNode; //Create variables
    xml = GetXmlHttpObject();
    xml.open(”GET”,”menu.xml”,false);
    xml.send(null);
    xsl = GetXmlHttpObject();
    xsl.open(”GET”,”menu.xsl”,false);
    xsl.send(null);
    menuNode = document.getElementById(”menu”);
    xsltProcessContext(new ExprContext(xml.responseXML), xsl.responseXML,
    menuNode);

    The algorithm is very simple. It is basically divided into 4 steps:
    1. Load the menu.xml
    2. Load the menu.xsl
    3. Get a container with id “menu”.
    4. Transform “menu.xml” with “menu.xsl” and append it into “menu”
    using ajaxslt.
    Still it doesn’t work. What am I doing wrong?

    Please note that menu.xml and menu.xsl are correcly formatted, the div with id “menu” is already loaded when it is called and GetXmlHttpObject() is a function I copied from w3schools site that returns an xmlhttpobject (depending on the browser).

Leave a Reply

About Me

I'm a software developer and consultant in San Francisco. I mostly develop web apps in Javascript, Java and Rails. There's a little more about me on my LinkedIn profile.

Recent Projects

wshlst.com: a group-oriented wish list website.

BoardsConsult​/​RotationTracker: a site to help medical residents prepare for the U.S. Medical Licensing Exam, and a related site to help medical schools evaluate and track the progress of the residents in their programs.

Jobs

I moderate a few completely free jobs mailing lists with RSS feeds and zero spam: XP jobs, Rails jobs and Mac development jobs. Also, my pals at Pivotal Labs have agile Rails and Java job openings.

Plug: Web Hosting

Looking for cheap shared web hosting and/or domain registration? I've been using DreamHost for years and I've been very happy with them. They offer tons of disk space and bandwidth, one-click installation for apps like WordPress and Gallery, unlimited domains, thousands of email accounts, private domain registration, and more. They are also a nice bunch of folks, not some big dumb company.