# Lambda Function - xml to json
## from_xml.js
```
/**
* The fromXML() method parses an XML string, constructing the JavaScript
* value or object described by the string.
*
* @function fromXML
* @param text {String} The string to parse as XML
* @param [reviver] {Function} If a function, prescribes how the value
* originally produced by parsing is transformed, before being returned.
* @returns {Object}
*/
var fromXML;
(function(exports) {
var UNESCAPE = {
"&": "&",
"<": "<",
">": ">",
"'": "'",
""": '"'
};
var ATTRIBUTE_KEY = "@";
var CHILD_NODE_KEY = "#";
exports.fromXML = fromXML = _fromXML;
function _fromXML(text, reviver) {
return toObject(parseXML(text), reviver);
}
function parseXML(text) {
var list = String.prototype.split.call(text, /<([^!<>?](?:'[\S\s]*?'|"[\S\s]*?"|[^'"<>])*|!(?:--[\S\s]*?--|\[[^\[\]'"<>]+\[[\S\s]*?]]|DOCTYPE[^\[<>]*?\[[\S\s]*?]|(?:ENTITY[^"<>]*?"[\S\s]*?")?[\S\s]*?)|\?[\S\s]*?\?)>/);
var length = list.length;
// root element
var root = {f: []};
var elem = root;
// dom tree stack
var stack = [];
for (var i = 0; i < length;) {
// text node
var str = list[i++];
if (str) appendText(str);
// child node
var tag = list[i++];
if (tag) parseNode(tag);
}
return root;
function parseNode(tag) {
var tagLength = tag.length;
var firstChar = tag[0];
if (firstChar === "/") {
// close tag
var closed = tag.replace(/^\/|[\s\/].*$/g, "").toLowerCase();
while (stack.length) {
var tagName = elem.n && elem.n.toLowerCase();
elem = stack.pop();
if (tagName === closed) break;
}
} else if (firstChar === "?") {
// XML declaration
appendChild({n: "?", r: tag.substr(1, tagLength - 2)});
} else if (firstChar === "!") {
if (tag.substr(1, 7) === "[CDATA[" && tag.substr(-2) === "]]") {
// CDATA section
appendText(tag.substr(8, tagLength - 10));
} else {
// comment
appendChild({n: "!", r: tag.substr(1)});
}
} else {
var child = openTag(tag);
appendChild(child);
if (tag[tagLength - 1] === "/") {
child.c = 1; // emptyTag
} else {
stack.push(elem); // openTag
elem = child;
}
}
}
function appendChild(child) {
elem.f.push(child);
}
function appendText(str) {
str = removeSpaces(str);
if (str) appendChild(unescapeXML(str));
}
}
function openTag(tag) {
var elem = {f: []};
tag = tag.replace(/\s*\/?$/, "");
var pos = tag.search(/[\s='"\/]/);
if (pos < 0) {
elem.n = tag;
} else {
elem.n = tag.substr(0, pos);
elem.t = tag.substr(pos);
}
return elem;
}
function parseAttribute(elem, reviver) {
if (!elem.t) return;
var list = elem.t.split(/([^\s='"]+(?:\s*=\s*(?:'[\S\s]*?'|"[\S\s]*?"|[^\s'"]*))?)/);
var length = list.length;
var attributes, val;
for (var i = 0; i < length; i++) {
var str = removeSpaces(list[i]);
if (!str) continue;
if (!attributes) {
attributes = {};
}
var pos = str.indexOf("=");
if (pos < 0) {
// bare attribute
str = ATTRIBUTE_KEY + str;
val = null;
} else {
// attribute key/value pair
val = str.substr(pos + 1).replace(/^\s+/, "");
str = ATTRIBUTE_KEY + str.substr(0, pos).replace(/\s+$/, "");
// quote: foo="FOO" bar='BAR'
var firstChar = val[0];
var lastChar = val[val.length - 1];
if (firstChar === lastChar && (firstChar === "'" || firstChar === '"')) {
val = val.substr(1, val.length - 2);
}
val = unescapeXML(val);
}
if (reviver) {
val = reviver(str, val);
}
addObject(attributes, str, val);
}
return attributes;
}
function removeSpaces(str) {
return str && str.replace(/^\s+|\s+$/g, "");
}
function unescapeXML(str) {
return str.replace(/(&(?:lt|gt|amp|apos|quot|#(?:\d{1,6}|x[0-9a-fA-F]{1,5}));)/g, function(str) {
if (str[1] === "#") {
var code = (str[2] === "x") ? parseInt(str.substr(3), 16) : parseInt(str.substr(2), 10);
if (code > -1) return String.fromCharCode(code);
}
return UNESCAPE[str] || str;
});
}
function toObject(elem, reviver) {
if ("string" === typeof elem) return elem;
var raw = elem.r;
if (raw) return raw;
var attributes = parseAttribute(elem, reviver);
var object;
var childList = elem.f;
var childLength = childList.length;
if (attributes || childLength > 1) {
// merge attributes and child nodes
object = attributes || {};
childList.forEach(function(child) {
if ("string" === typeof child) {
addObject(object, CHILD_NODE_KEY, child);
} else {
addObject(object, child.n, toObject(child, reviver));
}
});
} else if (childLength) {
// the node has single child node but no attribute
var child = childList[0];
object = toObject(child, reviver);
if (child.n) {
var wrap = {};
wrap[child.n] = object;
object = wrap;
}
} else {
// the node has no attribute nor child node
object = elem.c ? null : "";
}
if (reviver) {
object = reviver(elem.n || "", object);
}
return object;
}
function addObject(object, key, val) {
if ("undefined" === typeof val) return;
var prev = object[key];
if (prev instanceof Array) {
prev.push(val);
} else if (key in object) {
object[key] = [prev, val];
} else {
object[key] = val;
}
}
})(typeof exports === "object" && exports || {});
```