overthinkings
of Ruben Daniels
February 23, 2007 at 1:04 pm
· Filed under Tech, Javeline
After creating all the regexps and processing functions for the Xpath axis and constructs I ran into a problem. I had completely ignored the conditional statements that Xpath supports like ‘//div[@class=”dropdown” and @id+1=10]’. The entire Xpath library was already nearing 9KB of code. I felt it was really not a good thing to add much more code. Suddenly I remembered I was writing all this in javascript. One of the nice features of javascript is the fact that you can generate code and run it within the system itself. The conditional statements in Xpath look quite a lot like javascript actually. Just replace and by &&, or by || and = by == and you’re already a step in the right direction.
Still there were problems, the functions did not exist in normal javascript space. They even had unsupported characters like the ‘-’ sign. Another issue were the xpath statements within the conditions. I found that the only way to really solve this would be to somehow replace them with javascript statements. This required me to tokenize the statement a bit, and then replace the tokens again. Javascript has a nice feature when using regexp replace. Instead of giving a replace string as an argument, you can pass a function which is executed when the string is replaced. This way you can easily tokenize the different parts in the expression. This is how I detect the Xpath functions (I removed some functions to increase readability):
code = code.replace(/(concat|count)s*(/g,
function(x, match){return (d.push(match) - 1) + "F_";});
Of course this method has some theoretical flaws, just like any other regexps based parser. However, creating an Xpath parser that can execute 99% of the statements in around 10KB of code was close enough for me. So I deemed this acceptable.
After tokenizing the condition It was time to replace the tokens with a piece of javascript. Here is how I did that for xpath functions:
code = code.replace(/(d+)([FISX])_/g,
function(d, nr, type){
var value = data[type][nr];
if(type == "F"){
return "XPath.doXpathFunc('" + value + "', ";
}
//and below here for all other types.
});
So the Xpath lib is currently 12.2KB with full support for conditional statements and all the basic axis. It has been tested extensively in several big projects. Not all axis are in the parser. It’s very easy to add axis to the library, so be my guest, and please post your fixes and updates back to me. I released these libraries under the LGPL so you can use it in your projects and get Safari to work!
The Xpath processor has been extremely usefull in internet explorer as well. The Javeline skinning engine is completely abstracted using Xpath’s in the definition, which is in XML, but also applies the same Xpaths to the HTML document.
To get Safari really under control I created an XSLT parser in 4.6KB. It contains the basic tags but needs to be extended to contain the full spec. This XSLT parser has been used in production as well and has proven usefull for basic XSLT documents on Safari.
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>