gun/node_modules/aws-sdk/lib/xml/browser_parser.js
2014-04-01 00:47:41 -06:00

171 lines
5.0 KiB
JavaScript

var AWS = require('../core');
var inherit = AWS.util.inherit;
/**
* @api private
*/
AWS.XML.Parser = inherit({
constructor: function XMLParser(rules) {
this.rules = (rules || {}).members || {};
},
parse: function parse(xml) {
if (xml.replace(/^\s+/, '') === '') return {};
var result, error;
try {
if (window.DOMParser) {
var parser = new DOMParser();
result = parser.parseFromString(xml, 'text/xml');
if (result.documentElement === null) {
throw new Error('Cannot parse empty document.');
}
var isError = result.getElementsByTagName('parsererror')[0];
if (isError && (isError.parentNode === result ||
isError.parentNode.nodeName === 'body')) {
throw new Error(isError.getElementsByTagName('div')[0].textContent);
}
} else if (window.ActiveXObject) {
result = new window.ActiveXObject('Microsoft.XMLDOM');
result.async = false;
if (!result.loadXML(xml)) {
throw new Error('Parse error in document');
}
} else {
throw new Error('Cannot load XML parser');
}
} catch (e) {
error = e;
}
if (result && result.documentElement && !error) {
return this.parseStructure(result.documentElement, this.rules);
} else if (error) {
throw AWS.util.error(error || new Error(), {code: 'XMLParserError'});
} else { // empty xml document
return {};
}
},
parseStructure: function parseStructure(structure, rules) {
var data = {};
// force array members to always be present
AWS.util.each.call(this, rules, function(memberName, memberRules) {
if (memberRules.type === 'list') {
data[memberRules.name || memberName] = [];
}
});
for (var j = 0; j < structure.attributes.length; j++) {
var attr = structure.attributes[j];
var attrRule = rules[attr.name];
if (attrRule) {
var value = this.parseMember({ textContent: attr.value }, attrRule);
data[attrRule.name || attr.name] = value;
}
}
var child = structure.firstElementChild;
while (child) {
var rule = rules[child.nodeName] || {};
var key = rule.name || child.nodeName;
var inData = rule.flattened ? data[key] : null;
data[key] = this.parseMember(child, rule, inData);
child = child.nextElementSibling;
}
return data;
},
parseMap: function parseMap(map, rules, data) {
data = data || {};
var keyRules = rules.keys || {};
var valueRules = rules.members || {};
var keyName = keyRules.name || 'key';
var valueName = valueRules.name || 'value';
function run(item) {
var key = item.getElementsByTagName(keyName)[0].textContent;
var value = item.getElementsByTagName(valueName)[0];
value = this.parseMember(value, valueRules);
data[key] = value;
}
if (rules.flattened) {
run.call(this, map);
} else {
var child = map.firstElementChild;
while (child) {
run.call(this, child);
child = child.nextElementSibling;
}
}
return data;
},
parseList: function parseList(list, rules, data) {
data = data || [];
var memberRules = rules.members || {};
var memberName = memberRules.name || 'member';
if (rules.flattened) {
data.push(this.parseMember(list, memberRules));
} else {
var child = list.firstElementChild;
while (child) {
if (child.nodeName === memberName) {
data.push(this.parseMember(child, memberRules));
}
child = child.nextElementSibling;
}
}
return data;
},
parseMember: function parseMember(member, rules, data) {
if (!rules.type) {
if (member.childElementCount > 0) {
rules.type = 'structure';
} else {
rules.type = 'string';
}
}
if (rules.type === 'structure') {
return this.parseStructure(member, rules.members || {}, data);
} else if (rules.type === 'list') {
return this.parseList(member, rules, data);
} else if (rules.type === 'map') {
return this.parseMap(member, rules, data);
}
if (rules.type === 'string') {
if (member.attributes && member.attributes.encoding &&
member.attributes.encoding.value === 'base64') {
return AWS.util.base64.decode(member.textContent);
} else {
return member.textContent;
}
}
// return null for empty nodes of any other type
if (member.textContent === '') return null;
if (rules.type === 'integer') {
return parseInt(member.textContent, 10);
} else if (rules.type === 'float') {
return parseFloat(member.textContent);
} else if (rules.type === 'timestamp') {
return AWS.util.date.parseTimestamp(member.textContent);
} else if (rules.type === 'boolean') {
return member.textContent === 'true';
} else {
var msg = 'unhandled type: ' + rules.type;
throw AWS.util.error(new Error(msg), {code: 'XMLParserError'});
}
}
});