/* xml2json v 1.1 copyright 2005-2007 Thomas Frank This program is free software under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. It is distributed without any warranty. */ const parser = (xmlcode, ignoretags?, debug?) => { function deformateXml(str) { if (str) return str.replace(/&/g, "&").replace(/"/g, "\"").replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'"); return ""; } function no_fast_endings(str) { let values = str.split("/>"); for (let i = 1; i < values.length; i++) { let t = values[i - 1].substring(values[i - 1].lastIndexOf("<") + 1).split(" ")[0]; values[i] = ">" + values[i]; }; str = values.join(""); return str; } function isArray(obj) { return (Array.isArray ? Array.isArray(obj) : Object.prototype.toString.call(obj) == "[object Array]"); } let xmlobject: any = {}; let x: any = '' + xmlcode + ''; let cdatas = []; let cdataIndex = 0; while (x.indexOf(" 0) { let bindex = x.indexOf("", bindex); cdatas.push(x.substring(bindex + 9, eindex)); x = x.substring(0, bindex) + "§![CDATA[" + cdataIndex + "]]>" + x.substring(eindex + 3); cdataIndex++; } // x=x.replace(/<\?[^>]*>/g,"").replace(/<\!--[^>]*-->/g,"");//好像是去註解? x = x.replace(/<\?[^>]*>/g, ""); //.replace(/<\!--[]*-->/g,""); while (x.indexOf("", bindex); x = x.substring(0, bindex) + x.substring(eindex + 3); } x = x.replace(/\s*\/>/g, '/>'); x = no_fast_endings(x); x = x.replace(/<\//g, "§"); x = x.split("<"); let y = []; let level = 0; let opentags = []; for (let i = 1; i < x.length; i++) { x[i] = x[i].replace("§![CDATA[", "")[0].replace(/\s+/g, " "); if (tagname.indexOf(" ") > 0) tagname = tagname.substring(0, tagname.indexOf(" ")); opentags.push(tagname); level++; y.push(level + "<" + x[i].split("§")[0]); let ending = x[i]; let endingProcess = false; while (ending.replace(/^\s+/g, '').indexOf("§" + opentags[opentags.length - 1]) >= 0) { if (opentags[opentags.length - 1] != tagname && ending.indexOf("§" + opentags[opentags.length - 1]) > 0 && ending.substring(0, ending.indexOf("§" + opentags[opentags.length - 1])).replace(/^[\s]*[>]\s+|\s+$/g, '') != "") { y.push("" + (level + 1) + "<@text>" + ending.substring(0, ending.indexOf("§" + opentags[opentags.length - 1])).replace(/^[\s]*>/g, '')); } ending = ending.substring(ending.indexOf("§" + opentags[opentags.length - 1]) + opentags[opentags.length - 1].length + 2).replace(/^\s+>/g, ''); // xmlcode['aa'] = ending; // 這行到底在幹嘛? level--; opentags.pop(); endingProcess = true; } if (endingProcess && ending.replace(/^\s+|\s+$/g, '') != "") { y.push(level + 1 + "<@text>" + ending.replace(/^[\s]*>/g, '')); } }; let oldniva = -1; let objname = "xmlobject"; let currentObj = xmlobject; let parentStack = []; for (let i = 0; i < y.length; i++) { let niva = Number(y[i].split("<")[0]); let tagname = (y[i].split("<")[1].split(">")[0]).replace(/\s/g, ' '); let atts = tagname.match(/ ([^=]*)=[\s]*((\"[^\"|>]*\")|(\'[^\'|>]*\'))/g); if (tagname.indexOf(" ") > 0) tagname = tagname.substring(0, tagname.indexOf(" ")); let rest = y[i].substring(y[i].indexOf(">") + 1); if (niva <= oldniva) { let tabort = oldniva - niva + 1; for (let j = 0; j < tabort; j++) { currentObj = parentStack.pop(); } }; rest = rest.replace(/^\s+|\s+$/g, ''); // .replace(/^\s+|\s+$/g, '') <=這個叫做trim() let isstring = false; if (rest != "") { if (rest.match(/\<\!\[CDATA\[[0-9]+\]\]\>/g)) { rest = cdatas[Number(rest.replace(/\<\!\[CDATA\[/g, "").replace(/\]\]\>/g, ""))]; isstring = true; } else { rest = deformateXml(rest); isstring = true; } } else { if (atts || ((i + 1) < y.length && niva < Number(y[i + 1].split("<")[0]))) { rest = {}; } else { rest = ''; isstring = true; } }; if (atts) { if (isstring) { rest = { "@text": rest }; } rest["@"] = []; for (let m = 0; m < atts.length; m++) { let attname = atts[m].substring(0, atts[m].indexOf("=")).replace(/^\s+|\s+$/g, ''); let attvalue = atts[m].substring(atts[m].indexOf("=") + 1).replace(/^\s+/g, ''); ; if (attvalue != attvalue.replace(/^\'+|\'+$/g, '')) attvalue = attvalue.replace(/^\'+|\'+$/g, ''); else attvalue = attvalue.replace(/^\"+|\"+$/g, ''); rest["@"].push(attname); if (!rest[attname]) { rest[attname] = deformateXml(attvalue); } } } let already = false; for (const k in currentObj) { if (k == tagname) { already = true; break; } } if (already) { if (!isArray(currentObj[tagname])) { currentObj[tagname] = [currentObj[tagname]]; } currentObj[tagname].push(rest); } else { currentObj[tagname] = rest; } parentStack.push(currentObj); currentObj = rest; oldniva = niva; }; let result = xmlobject.JSONTAGWRAPPER; if (debug) { result = this.show_json_structure(result, debug); }; return result; }; export let xml2json = { parse: parser, show_json_structure: function (obj, debug, l) { let x = ''; try { if (!obj) { if (obj === null || obj === undefined) { x += '' + obj + ',\n'; } else { x += "'" + obj + "',\n"; } } else { let objType = typeof obj; if (Array.isArray ? Array.isArray(obj) : (obj == null ? String(obj) : (Object.prototype.toString.call(obj) == "[object Array]"))) { //obj isArray x += "[\n"; for (var i in obj) { //x += "'" + i.replace(/\'/g, "\\'") + "':"; x += this.show_json_structure(obj[i], false, 1); }; x += "],\n"; } else { if (objType == 'number' || objType == 'string' || objType == 'boolean') {//obj isValueType x += "'" + ("" + obj).replace(/\'/g, "\\'").replace(/\n/g, "\\n").replace(/\t/g, "\\t").replace(/\r/g, "\\r") + "',\n"; } else { if (objType == "function") { var v = obj + ""; x += v.substr(0, v.indexOf('{')) + "{\n...,\n},\n"; } else { x += "{\n"; for (var i in obj) { x += "'" + i.replace(/\'/g, "\\'") + "':"; x += this.show_json_structure(obj[i], false, 1); }; x += "},\n"; } } } } } catch (err) { x += err + ",\n"; } // if (!obj) { // return '' + obj; // } // if (obj.sort) { // x += "[\n"; // } // else { // x += "{\n"; // }; // for (var i in obj) { // if (!obj.sort) { // x += "'" + i.replace(/\'/g, "\\'") + "':"; // }; // if (typeof obj[i] == "object") { // x += this.show_json_structure(obj[i], false, 1); // } // else { // if (typeof obj[i] == "function") { // var v = 'function'//obj[i] + ""; // //v=v.replace(/\t/g,""); // x += v; // } // else // if (typeof obj[i] != "string") { // x += obj[i] + ",\n"; // } // else { // x += "'" + obj[i].replace(/\'/g, "\\'").replace(/\n/g, "\\n").replace(/\t/g, "\\t").replace(/\r/g, "\\r") + "',\n"; // } // } // }; // if (obj.sort) { // x += "],\n"; // } // else { // x += "},\n"; // }; if (!l) { x = x.substring(0, x.lastIndexOf(",")); x = x.replace(new RegExp(",\n}", "g"), "\n}"); x = x.replace(new RegExp(",\n]", "g"), "\n]"); var y = x.split("\n"); x = ""; var lvl = 0; for (let i = 0; i < y.length; i++) { if (y[i].indexOf("}") >= 0 || y[i].indexOf("]") >= 0) { lvl--; }; let tabs = ""; for (var j = 0; j < lvl; j++) { tabs += "\t"; }; x += tabs + y[i] + "\n"; if (y[i].indexOf("{") >= 0 || y[i].indexOf("[") >= 0) { lvl++; } }; if (debug == "html") { x = x.replace(//g, ">"); x = x.replace(/\n/g, "
").replace(/\t/g, "    "); }; if (debug == "compact") { x = x.replace(/\n/g, "").replace(/\t/g, ""); } }; return x; } }; if (!Array.prototype.push) { //@ts-ignore Array.prototype.push = function (x) { this[this.length] = x; return true; }; }; if (!Array.prototype.pop) { Array.prototype.pop = function () { var response = this[this.length - 1]; this.length--; return response; }; };