(xml: string)
| 99 | } |
| 100 | |
| 101 | export function xml2obj<T = any>(xml: string): T { |
| 102 | const parser = new XMLParser({ |
| 103 | ignoreAttributes: false, |
| 104 | attributeNamePrefix: "", |
| 105 | parseTagValue: true, |
| 106 | parseAttributeValue: false, |
| 107 | processEntities: true, |
| 108 | isArray: (name) => [TAG_VALUE, TAG_ARRAY, TAG_OBJECT].includes(name), |
| 109 | }); |
| 110 | const parsed = parser.parse(xml); |
| 111 | |
| 112 | // The parser keeps the XML declaration (<?xml version="1.0"?>) under the |
| 113 | // pseudo-tag "?xml". Skip it so that we always start the conversion at the |
| 114 | // first real node (i.e. <object>, <array> or <value>). |
| 115 | const withoutDeclaration = _.omit(parsed, "?xml"); |
| 116 | |
| 117 | const rootTag = Object.keys(withoutDeclaration)[0]; |
| 118 | |
| 119 | // fast-xml-parser treats every <object>, <array> and <value> element as an array |
| 120 | // because we configured the `isArray` option above. This means even the root |
| 121 | // element comes wrapped in an array. Unwrap it so that the recursive |
| 122 | // conversion logic receives the actual node object instead of an array – |
| 123 | // otherwise no children will be found and we would return an empty result. |
| 124 | const rootNode = _.castArray(withoutDeclaration[rootTag])[0]; |
| 125 | |
| 126 | return _fromGenericNode(rootTag, rootNode); |
| 127 | } |
no test coverage detected