UNPKG

craydent-xml-to-json

Version:
207 lines (204 loc) 8.64 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.__processChildren = __processChildren; exports.__processSiblings = __processSiblings; exports.default = xmlToJson; const craydent_error_1 = require("craydent.error"); const craydent_filltemplate_1 = require("craydent.filltemplate"); const craydent_isarray_1 = require("craydent.isarray"); const craydent_isstring_1 = require("craydent.isstring"); const craydent_strip_1 = require("craydent.strip"); const craydent_suid_1 = require("craydent.suid"); const __processAttributes_1 = require("../private/__processAttributes"); const craydent_merge_1 = require("craydent.merge"); const craydent_isempty_1 = require("craydent.isempty"); const craydent_isnull_1 = require("craydent.isnull"); function __processChildren(name, children, xml, refs, ignoreAttributes) { let child, i = 0, obj = {}; let nodename = name; if (!children.length && !ignoreAttributes) { const attributes = (0, __processAttributes_1.default)(xml, refs); if ((0, craydent_isempty_1.default)(attributes)) { obj[nodename] = ''; } else { obj[nodename] = (0, __processAttributes_1.default)(xml, refs); } } while (child = children[i++]) { let index = child.indexOf('>'), lindex = child.lastIndexOf('</'), attributes = ignoreAttributes ? {} : (0, __processAttributes_1.default)(child, refs), childXML = (0, craydent_strip_1.default)(child.substring(index + 1, lindex), '\n').trim(); if (children.length == 1) { // @ts-ignore childXML = xmlToJson(childXML, ignoreAttributes, refs); if (!(0, craydent_isstring_1.default)(childXML)) { childXML = (0, craydent_merge_1.default)(attributes, childXML); } obj[nodename] = childXML; } else { obj[nodename] = obj[nodename] || []; // @ts-ignore childXML = xmlToJson(childXML, ignoreAttributes, refs); if (!(0, craydent_isstring_1.default)(childXML)) { childXML = (0, craydent_merge_1.default)(attributes, childXML); } obj[nodename].push(childXML); } } return obj; } function __processSiblings(xml, refs, ignoreAttributes) { let parts = xml.split('<'), obj = {}, tag = "", node = "", etag, tagCount = 0; obj['#text'] = obj['#text'] || ""; for (let i = 0; i < parts.length; i++) { let part = parts[i]; if (!part) { continue; } /* istanbul ignore else */ if (!~part.indexOf('/>')) { /* istanbul ignore else */ if (!tag) { etag = part.indexOf('>'); if (!~etag) { if (!i) { obj['#text'] += (0, craydent_filltemplate_1.default)((0, craydent_strip_1.default)(part, ['\n', ' ']), refs); } else { node += part; } continue; } tag = part.split(/\s|>/)[0]; tagCount++; node += `<${part}`; continue; } else if (part.indexOf(tag) == 0) { tagCount++; } else if (part.indexOf(`/${tag}>`) == 0) { tagCount--; } } else if (!tagCount) { tag = part.replace('/>', '').trim(); } etag = part.indexOf(`/${tag}>`); if (!~etag) { let selfClosing = new RegExp(`${tag}(\\s*)/>`); const matching = part.match(selfClosing); if (matching && !(0, craydent_isnull_1.default)(matching[1])) { etag = part.search(selfClosing) + matching[1].length; } } if (!tagCount && ~etag) { let text = (0, craydent_strip_1.default)(part.substr(etag + tag.length + 2), ['\n', ' ']); if (text) { obj['#text'] += (0, craydent_filltemplate_1.default)(text, refs); } node += `<${part.substring(0, etag + tag.length + 2)}`; if (obj[tag]) { if (!(0, craydent_isarray_1.default)(obj[tag])) { obj[tag] = [obj[tag]]; } // @ts-ignore let child = xmlToJson(node, ignoreAttributes, refs); obj['#text'] += child['#text'] || ''; obj[tag].push(child[tag]); } else { // @ts-ignore obj = (0, craydent_merge_1.default)(obj, xmlToJson(node, ignoreAttributes, refs)); } tag = "", node = ""; } else { node += `<${part}`; } } if (!obj['#text'] && !(obj['#text'] = (0, craydent_filltemplate_1.default)(node, refs))) { delete obj['#text']; } return obj; } function xmlToJson(xml, ignoreAttributes, _refs) { /*|{ "info": "Converts XML to JSON", "category": "XML to JSON", "parameters":[ {"xml": "(String|XMLDocument) XML string or XML DOM"}, {"ignoreAttributes?": "(Bool) Flag to ignore attributes"}], "overloads":[], "url": "http://www.craydent.com/library/1.9.3/docs#xmlToJson", "returnType": "(Object)" }|*/ try { xml = xml.outerHTML || xml; let ids = [], rtn = xml; let raws = xml.match(/<\!\[CDATA\[(.*?)\]\]>/g) || []; xmlToJson.refs = xmlToJson.refs || {}; for (let i = 0, len = raws.length; i < len; i++) { let id = (0, craydent_suid_1.default)(); ids.push(id); xmlToJson.refs[id] = raws[i].replace(/<\!\[CDATA\[(.*?)\]\]>/, '$1'); xml = xml.replace(raws[i], `\${${id}}`); } xml = (0, craydent_strip_1.default)(xml.replace(/<\?.*?\?>/, ''), '\n').replace(/>\s*?\n\s*/g, '>'); let index = xml.indexOf('>'), nodename = xml.substring(0, index + 1).replace(/<([^\s\/]*)?(?:\s*?.*?)>/, '$1').replace(/<(\S*)?(?:\s*?.*?)>/, '$1'); let hasSiblings = false; /* istanbul ignore else */ if (nodename) { let parts = xml.split(nodename), child = "", children = [], openCount = 0; // break down construct string of children for (let i = 0, len = parts.length; i < len; i++) { let part = parts[i] = (0, craydent_strip_1.default)(parts[i], '\n'); if (!(openCount) && (part == ">" /* || part == "><" */)) { child += ">"; children.push(child); child = part.substr(1) + nodename; } else { /* istanbul ignore else */ if (part.slice(-1) == "<") { openCount++; } else if (~part.indexOf("</") || part.slice(-2) == "/>") { openCount--; let offset = 2; if (part == "/>") { offset = 1; } if (!openCount && i != len - offset) { hasSiblings = true; } } child += part + nodename; } } if (children.length == 1 && children[0] == xml && hasSiblings) { children = []; } // when there are different nodes const xmlWithoutSelfClosing = xml.replace(new RegExp(`<${nodename}[^>]*?/>`, 'g'), ''); let scount = (xmlWithoutSelfClosing.match(new RegExp(`<${nodename}.*?>`, 'g')) || []).length, ecount = (xmlWithoutSelfClosing.match(new RegExp(`</${nodename}>`, 'g')) || []).length; if (xmlWithoutSelfClosing && !children.length && scount == ecount) { rtn = __processSiblings(xml, xmlToJson.refs, ignoreAttributes); } else { rtn = __processChildren(nodename, children, xml, xmlToJson.refs, ignoreAttributes); } } else if ((0, craydent_isstring_1.default)(rtn)) { rtn = (0, craydent_filltemplate_1.default)(rtn, xmlToJson.refs); } for (let i = 0, len = ids.length; i < len; i++) { delete xmlToJson.refs[ids[i]]; } return rtn; } catch (e) /* istanbul ignore next */ { craydent_error_1.default && (0, craydent_error_1.default)('xmlToJson', e); return null; } }