overthinkings
of Ruben Daniels
February 23, 2007 at 1:04 pm
· Filed under Tech, Javeline
Creating an Ajax application can be a lot of fun. Making your website or webapplication more dynamic, and seeing all that functionality coming together. However when its all done and you are happy with the result, the real trouble start. Getting the application to run on all the different browsers, Safari especially, proved to be a hard problem…
My Ajax framework (Javeline Platform) uses a lot of Xpath, and the application I was building uses many XSLT’s. To my dismay I discovered Safari to have no scripting support for Xpath and XSLT. While I was trying to execute Xpath in Internet Explorer on the HTML document I found a similar limitation. A solution had to be found.
After searching the web I found several XPath/XSLT implementations:
I always try to keep the socalled ‘footprint’ of the application as low as possible. Loading a more than 100KB library to just add some functionality that should’ve existed in the first place, was unacceptable. The JS-XPath library only extends the one already available in IE. So I started building an XPath implementation myself with only one goal in mind; Create the smallest Xpath and XSLT implementation in javascript possible.
If you are not interested in how to build an Xpath parser you can just skip to the ‘how to use it’ part.
Building an Xpath parser using a tokenizer/lexer had proven to take a lot of code. So, my approach would have to use a different type of parsing. I looked at regular expressions to parse the Xpath. By using several regexps, I could create a stack of objects. Each node consists of a reference to the processing function and the arguments that are given to that function when it is executed. On first run of the Xpath the parsetree is created and cached for future use. Here is an example of such a stack using JSON notation for the Xpath ‘//j:teleport/node()|text()’:
[[this.multiXpaths, [
[
[this.getAllNodes, ["teleport", false, "j"],
[this.getAnyNode, null]
],
[
[this.getTextNode, null]
]
]]]
So when executed this will execute 2 parsing stacks, the first one tries to find the j:teleport node. If it finds it, it will then look for any child node. If the end result doesn’t yield any nodes, the 2nd stack is run which tries to find a text node within the current context. This is exactly what we wanted the Xpath expression to do!
Pages: 1 2 3
Permalink
[…] Ruben Daniels was on a mission to create XPath and XSLT support that works on Safari. […]
Very good work. Did you know that later versions of Safari support XPath? It seems to be pretty buggy so maybe you will need this library for a while. Once again, great work!
This is extactly what I am looking for. Great Work. How can I help on your mission to get full XSLT support for all browsers.
Ruben wrote @ February 25th, 2007 at 12:24 pm
Hi Dean, I know there is support in the later versions of Safari, but when I tried it, it was so buggy that it couldn’t be used in production. So this lib is usefull for that for now :). And IE will not have Xpath support for the HTMLDocument for a long time, which is where this lib comes in handy as well.
Francisco wrote @ February 26th, 2007 at 10:57 pm
Have you seen the Formfaces (www.formfaces.com) implementation of XPath, it is used heavily for its XForms implementation
Thank you very much. I was shocked when I discovered that Safari does not support XSLT transformations. I did not want to use a heavy library such as Sarissa, so I am happy that thery is a more lightweight alternative. I’ll definitely try your code and let you know if it works.
[…] Ruben Daniels was on a mission to create XPath and XSLT support that works on Safari. […]
Unfortunately it does not work. I assume I use some XSLT elements in my template that the library does not implement. Thanks anyway.
Just tried this in the latest webkit .. I immediately get undefined variable errors for “TAGNAME”. Looking in the XSLT.js, I see TAGNAME being used, but it’s never defined. Am I missing something?
Ruben wrote @ March 6th, 2007 at 10:26 pm
Hi Darrel,
It was missing:
TAGNAME = IS_IE ? “baseName” : “localName”;
I’ve just uploaded a new version. You can also add this to the XSLT.js file.
Thanks for letting me know.
Ruben
could you post a more robust example of the XSLT? I’ve spent the last two days attempting to replicate via DOM tree crawling what I did in client-side XSLT just so someone can see my site in Safari.
Finding your solution i breathed a sigh of relief. I attempted to plug in this solution to my code but so far i have been unable to make any progress.
Matt wrote @ April 20th, 2007 at 12:35 am
Hey, great job on this code. When I replace my normal XSLTProcessor(); in my code , I get a Kernel not defined error in firefox through the error console, it seems like it cannot perform the getObject function referenced in the .js Any ideas?
Johann wrote @ May 17th, 2007 at 7:42 pm
Great idea, but I tried out XSLT via iframes and that worked as well.
I wrote about adding support for Safari via iframes to my xslt.js script.
Dan wrote @ June 7th, 2007 at 1:08 pm
You’re doing great Ruben.
doug wrote @ June 7th, 2007 at 8:02 pm
I also was shocked to find current versions of safari don’t support xslt transformations from js. I am hopeful that your solution will work for me. Unfortunately, I am also getting the Kernel undefined error that Matt mentions above. I have not been able to find any reference for resolving the Kernel reference. I am running macosx 10.4.9 and safari 2.0.4. Any ideas?
Ruben wrote @ June 7th, 2007 at 10:25 pm
Many people have requested for a working example of the XSLT lib. I’ve updated the XSLT implementation with several more tags as well as in a joined effort with Sarissa and Sarissa users created a working demo. For now you can download that here: http://developer.javeline.net/downloads.php
Ruben,
I would love to switch to your JS implementation, it would make our lives so much simpler. I need to have a few more features built out before I do. Are you planning on adding support for: xsl:key, xsl:variable, xsl:call-template, and xsl:sort in an upcoming version?
Scott
Ruben wrote @ June 12th, 2007 at 6:15 pm
Hi Scott,
Actually those are in progress. Jean-Sebastien Baklouti is working on this right now. You can join the Javeline contributor mailinglist if you’d like to follow the progress. Go to http://developer.javeline.net/mailinglists.php to subscribe yourself.
Ruben
Kelly wrote @ October 27th, 2007 at 2:41 am
Just to add some criticism… I looked into using this script but I was turned off by your browser detection. Its so web 1.0. Last I knew object detection was the way to go.
http://www.quirksmode.org/js/support.html
Ruben wrote @ November 7th, 2007 at 9:41 am
Hi Kelly,
I know what you mean. The library now works together with Sarissa which, I think, does do that correctly. Javeline PlatForm still has some browser detection stuff in there. It is a todo item to fix that. Thanks for your suggestion.
Ruben
Hi Ruben,
Thanks for this… but I’ve found a bug in bootstrapping the outer template while running the example_on_xml (the one which matches “/” and then xsl:apply-templates select=”/Drive”).
Actually there’s another buglet which breaks on Konqueror and it involves the assumption that only HTML element nodes can have a ’style’ attribute (in getChildNode()) but I’ve fixed that in my copy.
The first bug is a bit more of a problem, though. If you have a look at the output in that example you should see that you’re missing the top level “Boot Disk C:” and the “My Documents” child is pushed down.
I’d appreciate any help you can give me in tracking that down - I don’t mind fixing it myself, but I thought maybe you’ve got an idea already where I should be looking, and I’m finding it really time consuming tracing through the code.
Thanks again.
Richard
Ruben wrote @ November 28th, 2007 at 11:20 am
Hi Richard,
I’ve found the bug and the solution. In the first if of appyt-templates it should be
if(t){
this.parseChildren(t == this.templates[”/”] ? context.ownerDocument : context, t[0], t[1], result);
}
if you could give me the changes you made I can incorporate them in a new package.
Thanks,
Ruben
Just came across your solution and it works like a charm. I had previously banged my head repeatedly for a day trying various xpath solutions and libraries and managed to create a short and elegant solution that worked in both Firefox and IE, but alas not Safari.
Anyway, thanks a lot for sharing this.
David
Hi, Theare is existed yet another xpath implementation by JavaScript.
http://coderepos.org/share/wiki/JavaScript-XPath/
This library is written by amachang who is known famous JavaScript hacker in Japan.
It is so faster than another js-xpath library. Please try it!
Thanks.
[…] XPath implementation for Javascript manipulation of the DOM, but there’s a very compact XPath and XSLT library for Safari. The CSS and Javascript is all open, so feel free to have a […]
Sumit wrote @ January 19th, 2008 at 1:56 am
Thanks for writing the XSLT wrapper. This link http://www.javeline.net/uploads/xslt-xpath-safari-full.zip is dead one (404). Like some others, I’m also getting Kernel not found error, looks like some file is missing. Can you please repost your code?
Ruben wrote @ February 14th, 2008 at 8:20 am
Hi Sumit,
Please visit http://developer.javeline.net/downloads.php for the latest version. I edited above posts as well.
Kind Regards,
Ruben Daniels
Henrik wrote @ March 8th, 2008 at 7:03 pm
I’am working on an “Full” XPath version 1.0 implementation in pure JavaScript. And it’s only 10K minified. Try it out llamalab.com/js/xpath/
Do your implementation support namespace ?
I would like to try to include your XPath lib into my XForms engine.
But somes features are required. Please contact me if we can colaborate.
Ruben wrote @ June 18th, 2008 at 8:28 pm
I think it does actually. It’s not properly done, but if you user “ns:blah” in your query, it will find elements in the ns namespace. You won’t be able to select based on a url though. Cool that you are working on an XForms engine. Javeline PlatForm has implemented XForms as well. (http://developer.javeline.net). I understand why you need a library like this for an XForms implementation: the custom model functions are quite hard to add to the c++ xpath implementation, I haven’t found a real solution for this. Would be cool if you could give me some pointers on your ideas for this. We might be able to collaborate on it.
HTML-Tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>