Querying XML documents
It's fine until you face though times and you have to find this:
<fancynamespace:tag color="green" size="huge">Kiwi</fancynamespace:tag>
or a normal-sized Kiwi, that's even harder!
You think you have a solution
Then you try $xmlDoc.find('fancynamespace\\:tag')
which works fine in Firefox but not in Chrome. If you decide to ignore the namespace and query only for tag: $xmlDoc.find('tag')
, that will work in Chrome but not in Firefox.
nodeFilter
nodeFilter is a tiny little jQuery plugin which helps you to write selectors for XML elements, even for those with namespaces. It was ispired by these few lines of code:
$.fn.filterNode = function(name) {
return this.find('*').filter(function() {
return this.nodeName === name;
});
};
which quickly showed its disadvantage. Because it only considers the nodeName (fancynamespace:tag)
it will fail even with a slightly complex query: ('fancynamespace:tag[color="red"][size="huge]')
nodeFilter solves this problem by splitting up the entire query string with this tiny regexp /(?=\[)/g
, comparing the nodeName with the very first result of split array, then applying the rest of the results to the target element with $.is
.
I also created a little comparison table to show, how $.find
works in a different browser (when it comes to namespaces), and what you actually get with nodeFilter:
Firefox
| | `prefix:tag` | `prefix\\:tag` | `tag` | `prefix:tag[color="green"]` |
| ------------- |:------------:|:----------------:|:-----:|:-------------------------------:|
| $.find |0 |6 |0 |0 |
| $.nodeFilter |6 |0 |0 |1 |
Chrome
| | `prefix:tag` | `prefix\\:tag` | `tag` | `prefix:tag[color="green"]` |
| ------------- |:------------:|:----------------:|:-----:|:-------------------------------:|
| $.find |0 |0 |6 |0 |
| $.nodeFilter |6 |0 |0 |1 |