UNPKG

fast-xml-parser

Version:

Validate XML, Parse XML, Build XML without C/C++ based libraries

124 lines (104 loc) 3.5 kB
'use strict'; import XmlNode from './xmlNode.js'; const METADATA_SYMBOL = XmlNode.getMetaDataSymbol(); /** * * @param {array} node * @param {any} options * @returns */ export default function prettify(node, options) { return compress(node, options); } /** * * @param {array} arr * @param {object} options * @param {string} jPath * @returns object */ function compress(arr, options, jPath) { let text; const compressedObj = {}; //This is intended to be a plain object for (let i = 0; i < arr.length; i++) { const tagObj = arr[i]; const property = propName(tagObj); let newJpath = ""; if (jPath === undefined) newJpath = property; else newJpath = jPath + "." + property; if (property === options.textNodeName) { if (text === undefined) text = tagObj[property]; else text += "" + tagObj[property]; } else if (property === undefined) { continue; } else if (tagObj[property]) { let val = compress(tagObj[property], options, newJpath); const isLeaf = isLeafTag(val, options); if (tagObj[":@"]) { assignAttributes(val, tagObj[":@"], newJpath, options); } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) { val = val[options.textNodeName]; } else if (Object.keys(val).length === 0) { if (options.alwaysCreateTextNode) val[options.textNodeName] = ""; else val = ""; } if (tagObj[METADATA_SYMBOL] !== undefined && typeof val === "object" && val !== null) { val[METADATA_SYMBOL] = tagObj[METADATA_SYMBOL]; // copy over metadata } if (compressedObj[property] !== undefined && Object.prototype.hasOwnProperty.call(compressedObj, property)) { if (!Array.isArray(compressedObj[property])) { compressedObj[property] = [compressedObj[property]]; } compressedObj[property].push(val); } else { //TODO: if a node is not an array, then check if it should be an array //also determine if it is a leaf node if (options.isArray(property, newJpath, isLeaf)) { compressedObj[property] = [val]; } else { compressedObj[property] = val; } } } } // if(text && text.length > 0) compressedObj[options.textNodeName] = text; if (typeof text === "string") { if (text.length > 0) compressedObj[options.textNodeName] = text; } else if (text !== undefined) compressedObj[options.textNodeName] = text; return compressedObj; } function propName(obj) { const keys = Object.keys(obj); for (let i = 0; i < keys.length; i++) { const key = keys[i]; if (key !== ":@") return key; } } function assignAttributes(obj, attrMap, jpath, options) { if (attrMap) { const keys = Object.keys(attrMap); const len = keys.length; //don't make it inline for (let i = 0; i < len; i++) { const atrrName = keys[i]; if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) { obj[atrrName] = [attrMap[atrrName]]; } else { obj[atrrName] = attrMap[atrrName]; } } } } function isLeafTag(obj, options) { const { textNodeName } = options; const propCount = Object.keys(obj).length; if (propCount === 0) { return true; } if ( propCount === 1 && (obj[textNodeName] || typeof obj[textNodeName] === "boolean" || obj[textNodeName] === 0) ) { return true; } return false; }