home mail me! syndication

overthinkings

of Ruben Daniels

Getting Xpath/XSLT support into Safari

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

30 Comments »

  Ajaxian » XPath/XSLT support in Safari wrote @ February 24th, 2007 at 1:51 am

[…] Ruben Daniels was on a mission to create XPath and XSLT support that works on Safari. […]

  Dean Edwards wrote @ February 24th, 2007 at 7:57 pm

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!

  Edward Kepler wrote @ February 25th, 2007 at 3:24 am

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

  attila szabo wrote @ February 28th, 2007 at 8:03 am

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.

  XPath/XSLT support in Safari wrote @ March 1st, 2007 at 3:42 pm

[…] Ruben Daniels was on a mission to create XPath and XSLT support that works on Safari. […]

  attila szabo wrote @ March 3rd, 2007 at 6:29 pm

Unfortunately it does not work. I assume I use some XSLT elements in my template that the library does not implement. Thanks anyway.

  Darrell Esau wrote @ March 6th, 2007 at 8:22 pm

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

  alektraunic wrote @ March 7th, 2007 at 8:19 pm

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

  Scott Mahoney wrote @ June 12th, 2007 at 4:26 pm

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

  Richard Hundt wrote @ November 28th, 2007 at 1:50 am

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

  David Dawnay wrote @ January 11th, 2008 at 3:36 pm

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

  Toru ŽYamaguchi wrote @ January 14th, 2008 at 7:08 am

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.

  Roll Your Own iPhone WordPress Theme - Matthew Botos wrote @ January 17th, 2008 at 2:33 am

[…] 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/

  Sébastien wrote @ June 18th, 2008 at 7:24 pm

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.

Your comment

HTML-Tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>

order clomid viagra online review cialis from canada cheap generic viagra compare cialis prices online buy cheap acomplia buy viagra no rx find discount viagra online cheap accutane online lasix pills drug cialis online purchase order discount viagra order viagra from canada cheap lasix online online propecia viagra information accutane prices cheap generic acomplia levitra generic cialis cost levitra without prescription propecia prescription buy acomplia cheap acomplia prices acomplia cheap discount viagra purchase cialis no rx buy cialis us synthroid buy cheap cialis cheap zithromax cialis drug lowest price lasix clomid online cheap order acomplia online viagra online cheapest soma prices order cialis no rx cialis without a prescription cheap clomid buy viagra without prescription cheap generic accutane buy propecia without prescription cialis free sample propecia pharmacy buy viagra from us zithromax cheap buy levitra generic propecia no rx viagra cialis tablets cialis without prescription generic viagra cheap generic accutane discount cialis online clomid cheap buy discount viagra cheap viagra on internet overnight viagra viagra uk buy viagra from canada buy generic accutane viagra no prescription zithromax pills cheapest synthroid prices discount synthroid where to buy zithromax cheapest zithromax prices buy soma without prescription accutane no prescription cheap levitra tablets find cheap cialis online levitra pills