How To Use Google’s Ajaxslt Library
Posted: September 30th, 2005 Tags: Howto, Javascript, XSLGoogle 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
November 6th, 2005 at 9:12 pm
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
November 6th, 2005 at 9:19 pm
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…
November 16th, 2005 at 2:34 pm
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
November 27th, 2005 at 8:55 pm
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
November 28th, 2005 at 10:36 am
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
December 10th, 2005 at 2:33 am
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
December 10th, 2005 at 4:23 pm
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.
December 11th, 2005 at 12:48 am
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
December 12th, 2005 at 8:54 am
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) )
January 11th, 2006 at 2:54 pm
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!
January 11th, 2006 at 5:58 pm
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
March 3rd, 2006 at 8:32 pm
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.
March 14th, 2006 at 2:26 pm
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!
March 14th, 2006 at 11:54 pm
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.
April 25th, 2006 at 5:43 pm
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
July 30th, 2006 at 6:48 am
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);
}
July 30th, 2006 at 8:57 am
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.)
July 30th, 2006 at 1:02 pm
thanks, erik, I am away now =), however how do you turn the debugging off.
kind regards
July 30th, 2006 at 1:11 pm
Excellent. To turn off debugging, I think all you have to do is set the global variables “xsltdebug” and “xpathdebug” to false.
July 30th, 2006 at 1:31 pm
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
August 28th, 2006 at 6:15 pm
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
August 28th, 2006 at 6:22 pm
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.
August 28th, 2006 at 6:26 pm
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”
…
August 31st, 2006 at 6:25 am
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
August 31st, 2006 at 8:37 am
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
February 16th, 2007 at 12:50 am
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
May 21st, 2007 at 3:39 am
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).
September 26th, 2008 at 6:06 am
Hi Erik,
Could you tell me how to implement the case:using xsl:include in a xsl file?
Thanks,
Jason
September 26th, 2008 at 8:19 am
Hi Jason,
I wrote these posts in 2005 and I haven’t used ajaxslt (or xslt for that matter) much since then. I ditched the approach in favor of building my UI completely in Javascript (no HTML, no CSS, just JS objects).
- Erik
October 30th, 2010 at 2:19 am
Hi, i wanna set js variable to xsl param…. any idea pls?
October 30th, 2010 at 7:20 pm
Winta — this might answer your question: http://www.eahanson.com/2005/10/23/setting-xsl-parameters-from-javascript-in-ajaxslt/