Blame | Last modification | View Log | RSS feed
// flattens an object (recursively!), similarly to Array#flatten// e.g. flatten({ a: { b: { c: "hello!" } } }); // => "hello!"function flatten(object) {var check = _.isPlainObject(object) && _.size(object) === 1;return check ? flatten(_.values(object)[0]) : object;}function XMLparse(xml) {var data = {};var isText = xml.nodeType === 3,isElement = xml.nodeType === 1,body = xml.textContent && xml.textContent.trim(),hasChildren = xml.children && xml.children.length,hasAttributes = xml.attributes && xml.attributes.length;// if it's text just return itif (isText) { return xml.nodeValue.trim(); }// if it doesn't have any children or attributes, just return the contentsif (!hasChildren && !hasAttributes) { return body; }// if it doesn't have children but _does_ have body content, we'll use thatif (!hasChildren && body.length) { data.text = body; }// if it's an element with attributes, add them to data.attributesif (isElement && hasAttributes) {data.attributes = _.reduce(xml.attributes, function(obj, name, id) {var attr = xml.attributes.item(id);obj[attr.name] = attr.value;return obj;}, {});}// recursively call #XMLparse over children, adding results to data_.each(xml.children, function(child) {var name = child.nodeName;// if we've not come across a child with this nodeType, add it as an object// and return hereif (!_.has(data, name)) {data[name] = XMLparse(child);return;}// if we've encountered a second instance of the same nodeType, make our// representation of it an arrayif (!_.isArray(data[name])) { data[name] = [data[name]]; }// and finally, append the new childdata[name].push(XMLparse(child));});// if we can, let's fold some attributes into the body_.each(data.attributes, function(value, key) {if (data[key] != null) { return; }data[key] = value;delete data.attributes[key];});// if data.attributes is now empty, get rid of itif (_.isEmpty(data.attributes)) { delete data.attributes; }// simplify to reduce number of final leaf nodes and returnreturn flatten(data);}