/ cloudformation-templates / node_modules / aws-cdk / node_modules / aws-sdk / lib / xml / browser_parser.js
browser_parser.js
1 var util = require('../util'); 2 var Shape = require('../model/shape'); 3 4 function DomXmlParser() { } 5 6 DomXmlParser.prototype.parse = function(xml, shape) { 7 if (xml.replace(/^\s+/, '') === '') return {}; 8 9 var result, error; 10 try { 11 if (window.DOMParser) { 12 try { 13 var parser = new DOMParser(); 14 result = parser.parseFromString(xml, 'text/xml'); 15 } catch (syntaxError) { 16 throw util.error(new Error('Parse error in document'), 17 { 18 originalError: syntaxError, 19 code: 'XMLParserError', 20 retryable: true 21 }); 22 } 23 24 if (result.documentElement === null) { 25 throw util.error(new Error('Cannot parse empty document.'), 26 { 27 code: 'XMLParserError', 28 retryable: true 29 }); 30 } 31 32 var isError = result.getElementsByTagName('parsererror')[0]; 33 if (isError && (isError.parentNode === result || 34 isError.parentNode.nodeName === 'body' || 35 isError.parentNode.parentNode === result || 36 isError.parentNode.parentNode.nodeName === 'body')) { 37 var errorElement = isError.getElementsByTagName('div')[0] || isError; 38 throw util.error(new Error(errorElement.textContent || 'Parser error in document'), 39 { 40 code: 'XMLParserError', 41 retryable: true 42 }); 43 } 44 } else if (window.ActiveXObject) { 45 result = new window.ActiveXObject('Microsoft.XMLDOM'); 46 result.async = false; 47 48 if (!result.loadXML(xml)) { 49 throw util.error(new Error('Parse error in document'), 50 { 51 code: 'XMLParserError', 52 retryable: true 53 }); 54 } 55 } else { 56 throw new Error('Cannot load XML parser'); 57 } 58 } catch (e) { 59 error = e; 60 } 61 62 if (result && result.documentElement && !error) { 63 var data = parseXml(result.documentElement, shape); 64 var metadata = getElementByTagName(result.documentElement, 'ResponseMetadata'); 65 if (metadata) { 66 data.ResponseMetadata = parseXml(metadata, {}); 67 } 68 return data; 69 } else if (error) { 70 throw util.error(error || new Error(), {code: 'XMLParserError', retryable: true}); 71 } else { // empty xml document 72 return {}; 73 } 74 }; 75 76 function getElementByTagName(xml, tag) { 77 var elements = xml.getElementsByTagName(tag); 78 for (var i = 0, iLen = elements.length; i < iLen; i++) { 79 if (elements[i].parentNode === xml) { 80 return elements[i]; 81 } 82 } 83 } 84 85 function parseXml(xml, shape) { 86 if (!shape) shape = {}; 87 switch (shape.type) { 88 case 'structure': return parseStructure(xml, shape); 89 case 'map': return parseMap(xml, shape); 90 case 'list': return parseList(xml, shape); 91 case undefined: case null: return parseUnknown(xml); 92 default: return parseScalar(xml, shape); 93 } 94 } 95 96 function parseStructure(xml, shape) { 97 var data = {}; 98 if (xml === null) return data; 99 100 util.each(shape.members, function(memberName, memberShape) { 101 if (memberShape.isXmlAttribute) { 102 if (Object.prototype.hasOwnProperty.call(xml.attributes, memberShape.name)) { 103 var value = xml.attributes[memberShape.name].value; 104 data[memberName] = parseXml({textContent: value}, memberShape); 105 } 106 } else { 107 var xmlChild = memberShape.flattened ? xml : 108 getElementByTagName(xml, memberShape.name); 109 if (xmlChild) { 110 data[memberName] = parseXml(xmlChild, memberShape); 111 } else if ( 112 !memberShape.flattened && 113 memberShape.type === 'list' && 114 !shape.api.xmlNoDefaultLists) { 115 data[memberName] = memberShape.defaultValue; 116 } 117 } 118 }); 119 120 return data; 121 } 122 123 function parseMap(xml, shape) { 124 var data = {}; 125 var xmlKey = shape.key.name || 'key'; 126 var xmlValue = shape.value.name || 'value'; 127 var tagName = shape.flattened ? shape.name : 'entry'; 128 129 var child = xml.firstElementChild; 130 while (child) { 131 if (child.nodeName === tagName) { 132 var key = getElementByTagName(child, xmlKey).textContent; 133 var value = getElementByTagName(child, xmlValue); 134 data[key] = parseXml(value, shape.value); 135 } 136 child = child.nextElementSibling; 137 } 138 return data; 139 } 140 141 function parseList(xml, shape) { 142 var data = []; 143 var tagName = shape.flattened ? shape.name : (shape.member.name || 'member'); 144 145 var child = xml.firstElementChild; 146 while (child) { 147 if (child.nodeName === tagName) { 148 data.push(parseXml(child, shape.member)); 149 } 150 child = child.nextElementSibling; 151 } 152 return data; 153 } 154 155 function parseScalar(xml, shape) { 156 if (xml.getAttribute) { 157 var encoding = xml.getAttribute('encoding'); 158 if (encoding === 'base64') { 159 shape = new Shape.create({type: encoding}); 160 } 161 } 162 163 var text = xml.textContent; 164 if (text === '') text = null; 165 if (typeof shape.toType === 'function') { 166 return shape.toType(text); 167 } else { 168 return text; 169 } 170 } 171 172 function parseUnknown(xml) { 173 if (xml === undefined || xml === null) return ''; 174 175 // empty object 176 if (!xml.firstElementChild) { 177 if (xml.parentNode.parentNode === null) return {}; 178 if (xml.childNodes.length === 0) return ''; 179 else return xml.textContent; 180 } 181 182 // object, parse as structure 183 var shape = {type: 'structure', members: {}}; 184 var child = xml.firstElementChild; 185 while (child) { 186 var tag = child.nodeName; 187 if (Object.prototype.hasOwnProperty.call(shape.members, tag)) { 188 // multiple tags of the same name makes it a list 189 shape.members[tag].type = 'list'; 190 } else { 191 shape.members[tag] = {name: tag}; 192 } 193 child = child.nextElementSibling; 194 } 195 return parseStructure(xml, shape); 196 } 197 198 /** 199 * @api private 200 */ 201 module.exports = DomXmlParser;