/ cloudformation-templates / node_modules / aws-cdk / node_modules / aws-sdk / lib / xml / node_parser.js
node_parser.js
1 var AWS = require('../core'); 2 var util = AWS.util; 3 var Shape = AWS.Model.Shape; 4 5 var xml2js = require('xml2js'); 6 7 /** 8 * @api private 9 */ 10 var options = { // options passed to xml2js parser 11 explicitCharkey: false, // undocumented 12 trim: false, // trim the leading/trailing whitespace from text nodes 13 normalize: false, // trim interior whitespace inside text nodes 14 explicitRoot: false, // return the root node in the resulting object? 15 emptyTag: null, // the default value for empty nodes 16 explicitArray: true, // always put child nodes in an array 17 ignoreAttrs: false, // ignore attributes, only create text nodes 18 mergeAttrs: false, // merge attributes and child elements 19 validator: null // a callable validator 20 }; 21 22 function NodeXmlParser() { } 23 24 NodeXmlParser.prototype.parse = function(xml, shape) { 25 shape = shape || {}; 26 27 var result = null; 28 var error = null; 29 30 var parser = new xml2js.Parser(options); 31 parser.parseString(xml, function (e, r) { 32 error = e; 33 result = r; 34 }); 35 36 if (result) { 37 var data = parseXml(result, shape); 38 if (result.ResponseMetadata) { 39 data.ResponseMetadata = parseXml(result.ResponseMetadata[0], {}); 40 } 41 return data; 42 } else if (error) { 43 throw util.error(error, {code: 'XMLParserError', retryable: true}); 44 } else { // empty xml document 45 return parseXml({}, shape); 46 } 47 }; 48 49 function parseXml(xml, shape) { 50 switch (shape.type) { 51 case 'structure': return parseStructure(xml, shape); 52 case 'map': return parseMap(xml, shape); 53 case 'list': return parseList(xml, shape); 54 case undefined: case null: return parseUnknown(xml); 55 default: return parseScalar(xml, shape); 56 } 57 } 58 59 function parseStructure(xml, shape) { 60 var data = {}; 61 if (xml === null) return data; 62 63 util.each(shape.members, function(memberName, memberShape) { 64 var xmlName = memberShape.name; 65 if (Object.prototype.hasOwnProperty.call(xml, xmlName) && Array.isArray(xml[xmlName])) { 66 var xmlChild = xml[xmlName]; 67 if (!memberShape.flattened) xmlChild = xmlChild[0]; 68 69 data[memberName] = parseXml(xmlChild, memberShape); 70 } else if (memberShape.isXmlAttribute && 71 xml.$ && Object.prototype.hasOwnProperty.call(xml.$, xmlName)) { 72 data[memberName] = parseScalar(xml.$[xmlName], memberShape); 73 } else if (memberShape.type === 'list' && !shape.api.xmlNoDefaultLists) { 74 data[memberName] = memberShape.defaultValue; 75 } 76 }); 77 78 return data; 79 } 80 81 function parseMap(xml, shape) { 82 var data = {}; 83 if (xml === null) return data; 84 85 var xmlKey = shape.key.name || 'key'; 86 var xmlValue = shape.value.name || 'value'; 87 var iterable = shape.flattened ? xml : xml.entry; 88 89 if (Array.isArray(iterable)) { 90 util.arrayEach(iterable, function(child) { 91 data[child[xmlKey][0]] = parseXml(child[xmlValue][0], shape.value); 92 }); 93 } 94 95 return data; 96 } 97 98 function parseList(xml, shape) { 99 var data = []; 100 var name = shape.member.name || 'member'; 101 if (shape.flattened) { 102 util.arrayEach(xml, function(xmlChild) { 103 data.push(parseXml(xmlChild, shape.member)); 104 }); 105 } else if (xml && Array.isArray(xml[name])) { 106 util.arrayEach(xml[name], function(child) { 107 data.push(parseXml(child, shape.member)); 108 }); 109 } 110 111 return data; 112 } 113 114 function parseScalar(text, shape) { 115 if (text && text.$ && text.$.encoding === 'base64') { 116 shape = new Shape.create({type: text.$.encoding}); 117 } 118 if (text && text._) text = text._; 119 120 if (typeof shape.toType === 'function') { 121 return shape.toType(text); 122 } else { 123 return text; 124 } 125 } 126 127 function parseUnknown(xml) { 128 if (xml === undefined || xml === null) return ''; 129 if (typeof xml === 'string') return xml; 130 131 // parse a list 132 if (Array.isArray(xml)) { 133 var arr = []; 134 for (i = 0; i < xml.length; i++) { 135 arr.push(parseXml(xml[i], {})); 136 } 137 return arr; 138 } 139 140 // empty object 141 var keys = Object.keys(xml), i; 142 if (keys.length === 0 || (keys.length === 1 && keys[0] === '$')) { 143 return {}; 144 } 145 146 // object, parse as structure 147 var data = {}; 148 for (i = 0; i < keys.length; i++) { 149 var key = keys[i], value = xml[key]; 150 if (key === '$') continue; 151 if (value.length > 1) { // this member is a list 152 data[key] = parseList(value, {member: {}}); 153 } else { // this member is a single item 154 data[key] = parseXml(value[0], {}); 155 } 156 } 157 return data; 158 } 159 160 /** 161 * @api private 162 */ 163 module.exports = NodeXmlParser;