Presenting XMLTree v.2.0
You may remember XMLTree, which I launched several months ago. In short, it's a plugin that generates a tree from XML data, allowing you to traverse and interrogate the data but also bind events to the various branches of the tree.
Version 2.0 is now here, and comes with a host of powerful new features, including:
Sub-trees: loading data from a web service
Sub-trees allow you to load data branch-by-branch rather than all at once. This means you can use XMLTree with a web service, which serves up the root-level data on load, and then branch-specific data as and when branches are expanded.
Imagine you have a tree showing the boroughs of London. When a branch is expanded, it should show all the bus numbers that serve that borough.
Let's assume the web service returns the following XML format for the root data:
1<boroughs>
2 <borough id='1'>Wandsworth</borough>
3 <borough id='2'>Hackney</borough>
4 <borough id='3'>Croydon</borough>
5 <!-- ... ... -->
6</boroughs>
Knowing that, here's our tree instantiation:
1var ws_url = 'my_web_service.php';
2new XMLTree({
3 fpath: ws_url,
4 container: '#tree',
5 attrsAsData: 'borough_id',
6 subTreeBranches: true,
7 subTreeRequest: function(li) {
8 return ws_url+'?borough_id='+li.data('borough_id');
9 }
10});
By using the attrsAsData param (see below), we ensure that any borough_id attributes from the XML are transfered over as element data onto the tree LIs.
That's critical, because it means that, when a branch is expanded, we can look up that piece of data to determine URL of the web service for loading the next set of data.
The URL is determined and returned by the subTreeRequest param, a callback function that fires when a sub-tree-able branch is expanded and to which the expanded branch's LI is automatically passed. So the URL returned will be something like my_web_service.php?borough_id=13
In summary: to start with, only the root-level data is loaded. The data that goes within branches is determined only when a branch is expanded, by making a separate call to the web service. Crucial information is passed to the web service so it knows what data is returned - in this case, the ID of the clicked branch.
Transfer XML attributes to classes/element data
Attributes in your XML can now be transfered over to the resultant mark-up - in the form of either classes or element data attributes on the branch LIs.
In either case, you can either specify that all attributes should be transferred over, or just some.
Other features
Other, more minor features in this release include:
- support for loading XML over JSONP internet requests
- ability to auto-open the tree at a specific point once it's loaded
- ability to output, ignore or output but hide attributes as branches
Head over here to download, get usage info or view a demo.
post a commentAdditions to XML tree; jQuery XML parsing
You may have seen my XMLTree plugin, posted a few weeks ago.
If you'll excuse the trumpet-blowing I do find this plugin among my most useful; I'm working on a number of projects right now that involve XML in the browser, and the ability to visualise it in a traversable tree is quiet satisfying.
New features (all documented on the script page) include:
- callback on resultant HTML - you can now specify a callback function which will be invoked after the tree has been generated. It is automatically passed a DOM reference to the tree ul so you can act on it.
- attributes - can now be ignored, hidden or shown. Hiding them is useful if you plan to traverse or interrogate the tree based on their existence or value, without wanting to show them to the user.
Bug fixes
This was an interesting one. With XMLTree you can either point it at an XML file for it to load, or manually pass it a well-formed string of XML.
In the latter case, it exploits a well-known (yet somewhat abused) perk of jQuery - that you can pass it a DOM or XML string and it will turn it into a nodeset.
But because this is intended for DOM creation, not XML creation, it assumes you're parsing an HTML document, not XML. The problem? If your XML contains any tags that share their names with any self-closing HTML tags, jQuery renders your XML invalid.
Consider the following example:
1var xml = "<root><link>http://www.mitya.co.uk</link></root>";
2console.log($(xml).html());
The output of that will be:
<link />http://www.mitya.co.uk
...which is obviously not what you'd wanted.
As a fix for this XMLTree now renames (secretly) all of the node names - but restores their original names on output.
Ideally, of course, I wouldn't be lazy and rely on jQuery to parse XML - there are native ways (albeit different ones for different browsers). But for now this fix works just fine.
Head over here to download, get usage info or view a demo.
post a commentAnnoyances with client-side XSL transformation
A current project of mine heavily involves XSL.
XSL is that rare thing: a technology that can run both on the client and on the server.This might be exciting if it wasn't so dubious; the likelihood of browsers and servers implementing a recommendation in equivalent fashion, just seems so unlikely.
That said, XSL does, I must admit, enjoy a pretty decent implementation in the browser, and with few cross-browser issues, too.
Naturally you won't want to be trying it in the likes of IE6 (which runs a very, very stripped-down version of XSL) but if you don't care about IE6, you should be fine.
Today, though, I did hit a snag: where XSL imports are concerned. Specifically, they don't work in Webkit browsers (Safari, Chrome).
This is only a problem when transforming your XSL through Javascript, i.e. within a webpage context - not if you're opening up the XML manually. In the latter case, your imports will work fine.
This is annoying, and it's not at all clear why Google/Apple don't add support for this.
Weirdness in Opera
As anyone close to me will tell you (or, rather, sigh and then tell you), my browser of choice is Opera. Now Opera does support XSL includes in the context of JS transformation... in a way.
If you load the XSL from a file, any XSL include statements within it will work.
1//utility function to load XML file and return as XML object
2function loadXMLDoc(dname) {
3 if (window.XMLHttpRequest)
4 xhttp=new XMLHttpRequest();
5 else
6 xhttp=new ActiveXObject("Microsoft.XMLHTTP");
7 xhttp.open("GET",dname,false);
8 xhttp.send("");
9 return xhttp.responseXML;
10}
11
12//load and parse XML & XSL files
13var xml = loadXMLDoc('some_xml_file.xml');
14var xsl = loadXMLDoc('some_xsl_file.xsl');
15
16//non-IE
17if (document.implementation && document.implementation.createDocument) {
18 xsltProcessor=new XSLTProcessor();
19 xsltProcessor.importStylesheet(xsl);
20 var output = xsltProcessor.transformToFragment(xml, document);
21//IE
22} else if (window.ActiveXObject)
23 var output = xml.transformNode(xsl);
24return output;
If, however, you specify and convert your XSL from a string, not from a file, you can forget about XSL includes.
1//prepare XML & XSL strings then parse into XML objects
2var xml = "<?xml version="1.0" encoding="ISO-8859-1"?><root></root>";
3var xsl = "<?xml version="1.0" encoding="ISO-8859-1"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match='/'></xsl:template></xsl:stylesheet>";
4xml = $.parseXML(xml);
5xsl = $.parseXML(xsl);
This would appear to be a bug. In both cases, the resultant xml and xsl vars are both typeof == 'XML Document Object'. In other words, they should be equivalent - but only the former approach allows XSL includes.
Looks like I'll be doing my XSL on the server after all.
post a commentXML Tree - visualise and traverse your XML
XMLTree, just posted in the scripts section, is a utility for visualising and traversing XML in tree format.
You point it to an XML file, or manually feed it XML, and it does the rest, turning your nodes into a traversable tree.
But it's more than that; you can stipulate callbacks to fire when a node is expanded/collapsed and/or clicked. Callbacks are passed certain standard arguments, such as a reference to the node that was clicked and the XPath to it.
Behold! I even made a lovely demo for you involving Nintendo characters:
You can also deep-link to a point or points within the tree, so that, on load, the tree opens at a specific point or points. By extension, this means the tree is refresh-friendly, i.e. it won't forget which nodes were open when you reload the page.
Head over here to download, get usage info or view a demo.
1 comments | post newUber-customisable video carousel
Hello 2011! Sorry for the hiatus, I've been away visiting family in Russia and then it was christmas and new year and, well, you get the idea.
Anyway it's not like I've not been busy. Behold, my new video carousel. Head over here to download, get usage info or view a demo.
This carousel can display both graphic and video slides (the latter using JWPlayer), and is super customisable.
Via the single XML config file it reads, you can control the position of the slide tabs (top, bottom, right, left), info area (left, right, none), control the transition type, auto-rotate speed and more.
Enjoy!
1 comments | post newXML-to-JSON remapper - now RSS friendly
I've had a great response to my XML-to-JSON convertor and remapper. Its ability to not only convert but also remap data on the fly, to your precise structural requirements, has gone down particularly well.
One flaw raised today, though, was that it didn't work with RSS fees. Standard XML feeds, yes, but not RSS. After some digging I realised why.
The plugin expected the iteration node (i.e. the repeated node whose data will form the sub-objects of your JSON data) to directly follow the root node, e.g.
1<root>
2 <news_story>
3 <headline>foo</headline>
4 <url>bar.html</url>
5 </news_story>
6</root>
But if your XML had more levels - such as the following, typical of RSS:
1<rss>
2 <channel>
3 <news_story>
4 <headline>foo</headline>
5 <url>bar.html</url>
6 </news_story>
7 </channel>
8</rss>
...it didn't play ball. This has been countered by the addition of a new second argument when calling the plugin, in which you pass a space-separated selector string matching the iteration node, so for the above two examples this would be 'root news_story' and 'rss channel news_story', respectively.
Happy days! Head over here to download, get usage info or view a demo.
I've also been asked about whether the plugin supports XML node attributes. No, but it will. Stay posted...
post a comment



