I changed the code to be more prototype-esque, and created a class
called XMLDoc. I may add more functionality to it later, hence the more
generic name, but you do something like this to convert XML to a hash:
XMLDoc = Class.create();
Object.extend(XMLDoc.prototype, {
initialize: function (xmlDoc) {
this.element = xmlDoc;
},
asHash: function () {
if (! this._xmlHash) {
this._xmlHash = this._nodeToHash(this.element);
}
return this._xmlHash;
},
_nodeToHash: function (node) {
Element.cleanWhitespace(node);
if ((node.attributes && node.attributes.length > 0)
|| (node.hasChildNodes() && node.childNodes[0].nodeType ==
1)) {
var localHash = {};
if (node.attributes && node.attributes.length >= 1) {
$A(node.attributes).each(function (attr) {
localHash[attr.nodeName] = [attr.nodeValue]; });
}
$A(node.childNodes).each(function (node) {
this._subNodeToHash(localHash, node); }.bindAsEventListener(this));
$H(localHash).each( function (pair) { if
(localHash[pair[0]].length == 1) { localHash[pair[0]] =
localHash[pair[0]][0]; } });
return localHash;
}
else {
return this._nodeAsText(node);
}
},
_subNodeToHash: function (hash, node) {
if (node.nodeType == 2) {
hash[node.localName] = this._nodeAsText(node);
}
else {
var key = node.tagName;
if (hash[key]) {
hash[key].push(this._nodeToHash(node));
}
else {
hash[key] = [ this._nodeToHash(node) ];
}
}
},
_nodeAsText: function (node) {
return node.textContent || node.innerText || node.text || '';
}
} );
Usage:
var doc = new XMLDoc(request.responseXML.documentElement);
var hash = doc.asHash();
So, this xml:
<document>
<item id="1" type="blah" />
<item>
<id>2</id>
<type>blah</type>
</item>
</document>
Becomes:
{
item: [
{
id: 1,
type: 'blah'
},
{
id: 2,
type: 'blah'
}
]
}
Dunno if anyone even cares, but hey, free code :)
Greg
_______________________________________________
Rails-spinoffs mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs