This commit is contained in:
2021-11-21 11:18:28 +01:00
parent 7a358eb836
commit 230b10b2a3
9339 changed files with 892519 additions and 62 deletions

280
node_modules/fast-xml-parser/src/json2xml.js generated vendored Normal file
View File

@@ -0,0 +1,280 @@
'use strict';
//parse Empty Node as self closing node
const buildOptions = require('./util').buildOptions;
const defaultOptions = {
attributeNamePrefix: '@_',
attrNodeName: false,
textNodeName: '#text',
ignoreAttributes: true,
cdataTagName: false,
cdataPositionChar: '\\c',
format: false,
indentBy: ' ',
supressEmptyNode: false,
tagValueProcessor: function(a) {
return a;
},
attrValueProcessor: function(a) {
return a;
},
};
const props = [
'attributeNamePrefix',
'attrNodeName',
'textNodeName',
'ignoreAttributes',
'cdataTagName',
'cdataPositionChar',
'format',
'indentBy',
'supressEmptyNode',
'tagValueProcessor',
'attrValueProcessor',
'rootNodeName', //when array as root
];
function Parser(options) {
this.options = buildOptions(options, defaultOptions, props);
if (this.options.ignoreAttributes || this.options.attrNodeName) {
this.isAttribute = function(/*a*/) {
return false;
};
} else {
this.attrPrefixLen = this.options.attributeNamePrefix.length;
this.isAttribute = isAttribute;
}
if (this.options.cdataTagName) {
this.isCDATA = isCDATA;
} else {
this.isCDATA = function(/*a*/) {
return false;
};
}
this.replaceCDATAstr = replaceCDATAstr;
this.replaceCDATAarr = replaceCDATAarr;
this.processTextOrObjNode = processTextOrObjNode
if (this.options.format) {
this.indentate = indentate;
this.tagEndChar = '>\n';
this.newLine = '\n';
} else {
this.indentate = function() {
return '';
};
this.tagEndChar = '>';
this.newLine = '';
}
if (this.options.supressEmptyNode) {
this.buildTextNode = buildEmptyTextNode;
this.buildObjNode = buildEmptyObjNode;
} else {
this.buildTextNode = buildTextValNode;
this.buildObjNode = buildObjectNode;
}
this.buildTextValNode = buildTextValNode;
this.buildObjectNode = buildObjectNode;
}
Parser.prototype.parse = function(jObj) {
if(Array.isArray(jObj) && this.options.rootNodeName && this.options.rootNodeName.length > 1){
jObj = {
[this.options.rootNodeName] : jObj
}
}
return this.j2x(jObj, 0).val;
};
Parser.prototype.j2x = function(jObj, level) {
let attrStr = '';
let val = '';
for (let key in jObj) {
if (typeof jObj[key] === 'undefined') {
// supress undefined node
} else if (jObj[key] === null) {
val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
} else if (jObj[key] instanceof Date) {
val += this.buildTextNode(jObj[key], key, '', level);
} else if (typeof jObj[key] !== 'object') {
//premitive type
const attr = this.isAttribute(key);
if (attr) {
attrStr += ' ' + attr + '="' + this.options.attrValueProcessor('' + jObj[key]) + '"';
} else if (this.isCDATA(key)) {
if (jObj[this.options.textNodeName]) {
val += this.replaceCDATAstr(jObj[this.options.textNodeName], jObj[key]);
} else {
val += this.replaceCDATAstr('', jObj[key]);
}
} else {
//tag value
if (key === this.options.textNodeName) {
if (jObj[this.options.cdataTagName]) {
//value will added while processing cdata
} else {
val += this.options.tagValueProcessor('' + jObj[key]);
}
} else {
val += this.buildTextNode(jObj[key], key, '', level);
}
}
} else if (Array.isArray(jObj[key])) {
//repeated nodes
if (this.isCDATA(key)) {
val += this.indentate(level);
if (jObj[this.options.textNodeName]) {
val += this.replaceCDATAarr(jObj[this.options.textNodeName], jObj[key]);
} else {
val += this.replaceCDATAarr('', jObj[key]);
}
} else {
//nested nodes
const arrLen = jObj[key].length;
for (let j = 0; j < arrLen; j++) {
const item = jObj[key][j];
if (typeof item === 'undefined') {
// supress undefined node
} else if (item === null) {
val += this.indentate(level) + '<' + key + '/' + this.tagEndChar;
} else if (typeof item === 'object') {
val += this.processTextOrObjNode(item, key, level)
} else {
val += this.buildTextNode(item, key, '', level);
}
}
}
} else {
//nested node
if (this.options.attrNodeName && key === this.options.attrNodeName) {
const Ks = Object.keys(jObj[key]);
const L = Ks.length;
for (let j = 0; j < L; j++) {
attrStr += ' ' + Ks[j] + '="' + this.options.attrValueProcessor('' + jObj[key][Ks[j]]) + '"';
}
} else {
val += this.processTextOrObjNode(jObj[key], key, level)
}
}
}
return {attrStr: attrStr, val: val};
};
function processTextOrObjNode (object, key, level) {
const result = this.j2x(object, level + 1);
if (object[this.options.textNodeName] !== undefined && Object.keys(object).length === 1) {
return this.buildTextNode(result.val, key, result.attrStr, level);
} else {
return this.buildObjNode(result.val, key, result.attrStr, level);
}
}
function replaceCDATAstr(str, cdata) {
str = this.options.tagValueProcessor('' + str);
if (this.options.cdataPositionChar === '' || str === '') {
return str + '<![CDATA[' + cdata + ']]' + this.tagEndChar;
} else {
return str.replace(this.options.cdataPositionChar, '<![CDATA[' + cdata + ']]' + this.tagEndChar);
}
}
function replaceCDATAarr(str, cdata) {
str = this.options.tagValueProcessor('' + str);
if (this.options.cdataPositionChar === '' || str === '') {
return str + '<![CDATA[' + cdata.join(']]><![CDATA[') + ']]' + this.tagEndChar;
} else {
for (let v in cdata) {
str = str.replace(this.options.cdataPositionChar, '<![CDATA[' + cdata[v] + ']]>');
}
return str + this.newLine;
}
}
function buildObjectNode(val, key, attrStr, level) {
if (attrStr && val.indexOf('<') === -1) {
return (
this.indentate(level) +
'<' +
key +
attrStr +
'>' +
val +
//+ this.newLine
// + this.indentate(level)
'</' +
key +
this.tagEndChar
);
} else {
return (
this.indentate(level) +
'<' +
key +
attrStr +
this.tagEndChar +
val +
//+ this.newLine
this.indentate(level) +
'</' +
key +
this.tagEndChar
);
}
}
function buildEmptyObjNode(val, key, attrStr, level) {
if (val !== '') {
return this.buildObjectNode(val, key, attrStr, level);
} else {
return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar;
//+ this.newLine
}
}
function buildTextValNode(val, key, attrStr, level) {
return (
this.indentate(level) +
'<' +
key +
attrStr +
'>' +
this.options.tagValueProcessor(val) +
'</' +
key +
this.tagEndChar
);
}
function buildEmptyTextNode(val, key, attrStr, level) {
if (val !== '') {
return this.buildTextValNode(val, key, attrStr, level);
} else {
return this.indentate(level) + '<' + key + attrStr + '/' + this.tagEndChar;
}
}
function indentate(level) {
return this.options.indentBy.repeat(level);
}
function isAttribute(name /*, options*/) {
if (name.startsWith(this.options.attributeNamePrefix)) {
return name.substr(this.attrPrefixLen);
} else {
return false;
}
}
function isCDATA(name) {
return name === this.options.cdataTagName;
}
//formatting
//indentation
//\n after each closing or self closing tag
module.exports = Parser;

144
node_modules/fast-xml-parser/src/nimndata.js generated vendored Normal file
View File

@@ -0,0 +1,144 @@
'use strict';
const char = function(a) {
return String.fromCharCode(a);
};
const chars = {
nilChar: char(176),
missingChar: char(201),
nilPremitive: char(175),
missingPremitive: char(200),
emptyChar: char(178),
emptyValue: char(177), //empty Premitive
boundryChar: char(179),
objStart: char(198),
arrStart: char(204),
arrayEnd: char(185),
};
const charsArr = [
chars.nilChar,
chars.nilPremitive,
chars.missingChar,
chars.missingPremitive,
chars.boundryChar,
chars.emptyChar,
chars.emptyValue,
chars.arrayEnd,
chars.objStart,
chars.arrStart,
];
const _e = function(node, e_schema, options) {
if (typeof e_schema === 'string') {
//premitive
if (node && node[0] && node[0].val !== undefined) {
return getValue(node[0].val, e_schema);
} else {
return getValue(node, e_schema);
}
} else {
const hasValidData = hasData(node);
if (hasValidData === true) {
let str = '';
if (Array.isArray(e_schema)) {
//attributes can't be repeated. hence check in children tags only
str += chars.arrStart;
const itemSchema = e_schema[0];
//const itemSchemaType = itemSchema;
const arr_len = node.length;
if (typeof itemSchema === 'string') {
for (let arr_i = 0; arr_i < arr_len; arr_i++) {
const r = getValue(node[arr_i].val, itemSchema);
str = processValue(str, r);
}
} else {
for (let arr_i = 0; arr_i < arr_len; arr_i++) {
const r = _e(node[arr_i], itemSchema, options);
str = processValue(str, r);
}
}
str += chars.arrayEnd; //indicates that next item is not array item
} else {
//object
str += chars.objStart;
const keys = Object.keys(e_schema);
if (Array.isArray(node)) {
node = node[0];
}
for (let i in keys) {
const key = keys[i];
//a property defined in schema can be present either in attrsMap or children tags
//options.textNodeName will not present in both maps, take it's value from val
//options.attrNodeName will be present in attrsMap
let r;
if (!options.ignoreAttributes && node.attrsMap && node.attrsMap[key]) {
r = _e(node.attrsMap[key], e_schema[key], options);
} else if (key === options.textNodeName) {
r = _e(node.val, e_schema[key], options);
} else {
r = _e(node.child[key], e_schema[key], options);
}
str = processValue(str, r);
}
}
return str;
} else {
return hasValidData;
}
}
};
const getValue = function(a /*, type*/) {
switch (a) {
case undefined:
return chars.missingPremitive;
case null:
return chars.nilPremitive;
case '':
return chars.emptyValue;
default:
return a;
}
};
const processValue = function(str, r) {
if (!isAppChar(r[0]) && !isAppChar(str[str.length - 1])) {
str += chars.boundryChar;
}
return str + r;
};
const isAppChar = function(ch) {
return charsArr.indexOf(ch) !== -1;
};
function hasData(jObj) {
if (jObj === undefined) {
return chars.missingChar;
} else if (jObj === null) {
return chars.nilChar;
} else if (
jObj.child &&
Object.keys(jObj.child).length === 0 &&
(!jObj.attrsMap || Object.keys(jObj.attrsMap).length === 0)
) {
return chars.emptyChar;
} else {
return true;
}
}
const x2j = require('./xmlstr2xmlnode');
const buildOptions = require('./util').buildOptions;
const convert2nimn = function(node, e_schema, options) {
options = buildOptions(options, x2j.defaultOptions, x2j.props);
return _e(node, e_schema, options);
};
exports.convert2nimn = convert2nimn;

42
node_modules/fast-xml-parser/src/node2json.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
'use strict';
const util = require('./util');
const convertToJson = function(node, options, parentTagName) {
const jObj = {};
// when no child node or attr is present
if (!options.alwaysCreateTextNode && (!node.child || util.isEmptyObject(node.child)) && (!node.attrsMap || util.isEmptyObject(node.attrsMap))) {
return util.isExist(node.val) ? node.val : '';
}
// otherwise create a textnode if node has some text
if (util.isExist(node.val) && !(typeof node.val === 'string' && (node.val === '' || node.val === options.cdataPositionChar))) {
const asArray = util.isTagNameInArrayMode(node.tagname, options.arrayMode, parentTagName)
jObj[options.textNodeName] = asArray ? [node.val] : node.val;
}
util.merge(jObj, node.attrsMap, options.arrayMode);
const keys = Object.keys(node.child);
for (let index = 0; index < keys.length; index++) {
const tagName = keys[index];
if (node.child[tagName] && node.child[tagName].length > 1) {
jObj[tagName] = [];
for (let tag in node.child[tagName]) {
if (node.child[tagName].hasOwnProperty(tag)) {
jObj[tagName].push(convertToJson(node.child[tagName][tag], options, tagName));
}
}
} else {
const result = convertToJson(node.child[tagName][0], options, tagName);
const asArray = (options.arrayMode === true && typeof result === 'object') || util.isTagNameInArrayMode(tagName, options.arrayMode, parentTagName);
jObj[tagName] = asArray ? [result] : result;
}
}
//add value
return jObj;
};
exports.convertToJson = convertToJson;

63
node_modules/fast-xml-parser/src/node2json_str.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
'use strict';
const util = require('./util');
const buildOptions = require('./util').buildOptions;
const x2j = require('./xmlstr2xmlnode');
//TODO: do it later
const convertToJsonString = function(node, options) {
options = buildOptions(options, x2j.defaultOptions, x2j.props);
options.indentBy = options.indentBy || '';
return _cToJsonStr(node, options, 0);
};
const _cToJsonStr = function(node, options, level) {
let jObj = '{';
//traver through all the children
const keys = Object.keys(node.child);
for (let index = 0; index < keys.length; index++) {
const tagname = keys[index];
if (node.child[tagname] && node.child[tagname].length > 1) {
jObj += '"' + tagname + '" : [ ';
for (let tag in node.child[tagname]) {
jObj += _cToJsonStr(node.child[tagname][tag], options) + ' , ';
}
jObj = jObj.substr(0, jObj.length - 1) + ' ] '; //remove extra comma in last
} else {
jObj += '"' + tagname + '" : ' + _cToJsonStr(node.child[tagname][0], options) + ' ,';
}
}
util.merge(jObj, node.attrsMap);
//add attrsMap as new children
if (util.isEmptyObject(jObj)) {
return util.isExist(node.val) ? node.val : '';
} else {
if (util.isExist(node.val)) {
if (!(typeof node.val === 'string' && (node.val === '' || node.val === options.cdataPositionChar))) {
jObj += '"' + options.textNodeName + '" : ' + stringval(node.val);
}
}
}
//add value
if (jObj[jObj.length - 1] === ',') {
jObj = jObj.substr(0, jObj.length - 2);
}
return jObj + '}';
};
function stringval(v) {
if (v === true || v === false || !isNaN(v)) {
return v;
} else {
return '"' + v + '"';
}
}
function indentate(options, level) {
return options.indentBy.repeat(level);
}
exports.convertToJsonString = convertToJsonString;

79
node_modules/fast-xml-parser/src/parser.d.ts generated vendored Normal file
View File

@@ -0,0 +1,79 @@
type X2jOptions = {
attributeNamePrefix: string;
attrNodeName: false | string;
textNodeName: string;
ignoreAttributes: boolean;
ignoreNameSpace: boolean;
allowBooleanAttributes: boolean;
parseNodeValue: boolean;
parseAttributeValue: boolean;
arrayMode: boolean | 'strict' | RegExp | ((tagName: string, parentTagName: string) => boolean);
trimValues: boolean;
cdataTagName: false | string;
cdataPositionChar: string;
parseTrueNumberOnly: boolean;
numParseOptions: strnumOptions;
tagValueProcessor: (tagValue: string, tagName: string) => string;
attrValueProcessor: (attrValue: string, attrName: string) => string;
stopNodes: string[];
alwaysCreateTextNode: boolean;
};
type strnumOptions = {
hex: boolean;
leadingZeros: boolean,
skipLike?: RegExp
}
type X2jOptionsOptional = Partial<X2jOptions>;
type validationOptions = {
allowBooleanAttributes: boolean;
};
type validationOptionsOptional = Partial<validationOptions>;
type J2xOptions = {
attributeNamePrefix: string;
attrNodeName: false | string;
textNodeName: string;
ignoreAttributes: boolean;
cdataTagName: false | string;
cdataPositionChar: string;
format: boolean;
indentBy: string;
supressEmptyNode: boolean;
tagValueProcessor: (tagValue: string) => string;
attrValueProcessor: (attrValue: string) => string;
};
type J2xOptionsOptional = Partial<J2xOptions>;
type ESchema = string | object | Array<string|object>;
type ValidationError = {
err: { code: string; msg: string, line: number, col: number };
};
export function parse(xmlData: string, options?: X2jOptionsOptional, validationOptions?: validationOptionsOptional | boolean): any;
export function convert2nimn(
node: any,
e_schema: ESchema,
options?: X2jOptionsOptional
): any;
export function getTraversalObj(
xmlData: string,
options?: X2jOptionsOptional
): any;
export function convertToJson(node: any, options?: X2jOptionsOptional): any;
export function convertToJsonString(
node: any,
options?: X2jOptionsOptional
): string;
export function validate(
xmlData: string,
options?: validationOptionsOptional
): true | ValidationError;
export class j2xParser {
constructor(options: J2xOptionsOptional);
parse(options: any): any;
}
export function parseToNimn(
xmlData: string,
schema: any,
options: Partial<X2jOptions>
): any;

76
node_modules/fast-xml-parser/src/parser.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
'use strict';
const nodeToJson = require('./node2json');
const xmlToNodeobj = require('./xmlstr2xmlnode');
const x2xmlnode = require('./xmlstr2xmlnode');
const buildOptions = require('./util').buildOptions;
const validator = require('./validator');
exports.parse = function(xmlData, givenOptions = {}, validationOption) {
if( validationOption){
if(validationOption === true) validationOption = {}
const result = validator.validate(xmlData, validationOption);
if (result !== true) {
throw Error( result.err.msg)
}
}
if(givenOptions.parseTrueNumberOnly
&& givenOptions.parseNodeValue !== false
&& !givenOptions.numParseOptions){
givenOptions.numParseOptions = {
leadingZeros: false,
}
}
let options = buildOptions(givenOptions, x2xmlnode.defaultOptions, x2xmlnode.props);
const traversableObj = xmlToNodeobj.getTraversalObj(xmlData, options)
//print(traversableObj, " ");
return nodeToJson.convertToJson(traversableObj, options);
};
exports.convertTonimn = require('./nimndata').convert2nimn;
exports.getTraversalObj = xmlToNodeobj.getTraversalObj;
exports.convertToJson = nodeToJson.convertToJson;
exports.convertToJsonString = require('./node2json_str').convertToJsonString;
exports.validate = validator.validate;
exports.j2xParser = require('./json2xml');
exports.parseToNimn = function(xmlData, schema, options) {
return exports.convertTonimn(exports.getTraversalObj(xmlData, options), schema, options);
};
function print(xmlNode, indentation){
if(xmlNode){
console.log(indentation + "{")
console.log(indentation + " \"tagName\": \"" + xmlNode.tagname + "\", ");
if(xmlNode.parent){
console.log(indentation + " \"parent\": \"" + xmlNode.parent.tagname + "\", ");
}
console.log(indentation + " \"val\": \"" + xmlNode.val + "\", ");
console.log(indentation + " \"attrs\": " + JSON.stringify(xmlNode.attrsMap,null,4) + ", ");
if(xmlNode.child){
console.log(indentation + "\"child\": {")
const indentation2 = indentation + indentation;
Object.keys(xmlNode.child).forEach( function(key) {
const node = xmlNode.child[key];
if(Array.isArray(node)){
console.log(indentation + "\""+key+"\" :[")
node.forEach( function(item,index) {
//console.log(indentation + " \""+index+"\" : [")
print(item, indentation2);
})
console.log(indentation + "],")
}else{
console.log(indentation + " \""+key+"\" : {")
print(node, indentation2);
console.log(indentation + "},")
}
});
console.log(indentation + "},")
}
console.log(indentation + "},")
}
}

92
node_modules/fast-xml-parser/src/read.js generated vendored Normal file
View File

@@ -0,0 +1,92 @@
'use strict';
// Copyright 2013 Timothy J Fontaine <tjfontaine@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE
/*
Read any stream all the way to the end and trigger a single cb
const http = require('http');
const rte = require('readtoend');
http.get('http://nodejs.org', function(response) {
rte.readToEnd(response, function(err, body) {
console.log(body);
});
});
*/
let stream = require('stream');
const util = require('util');
if (!stream.Transform) {
stream = require('readable-stream');
}
function ReadToEnd(opts) {
if (!(this instanceof ReadToEnd)) {
return new ReadToEnd(opts);
}
stream.Transform.call(this, opts);
this._rte_encoding = opts.encoding || 'utf8';
this._buff = '';
}
module.exports = ReadToEnd;
util.inherits(ReadToEnd, stream.Transform);
ReadToEnd.prototype._transform = function(chunk, encoding, done) {
this._buff += chunk.toString(this._rte_encoding);
this.push(chunk);
done();
};
ReadToEnd.prototype._flush = function(done) {
this.emit('complete', undefined, this._buff);
done();
};
ReadToEnd.readToEnd = function(stream, options, cb) {
if (!cb) {
cb = options;
options = {};
}
const dest = new ReadToEnd(options);
stream.pipe(dest);
stream.on('error', function(err) {
stream.unpipe(dest);
cb(err);
});
dest.on('complete', cb);
dest.resume();
return dest;
};

108
node_modules/fast-xml-parser/src/util.js generated vendored Normal file
View File

@@ -0,0 +1,108 @@
'use strict';
const nameStartChar = ':A-Za-z_\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD';
const nameChar = nameStartChar + '\\-.\\d\\u00B7\\u0300-\\u036F\\u203F-\\u2040';
const nameRegexp = '[' + nameStartChar + '][' + nameChar + ']*'
const regexName = new RegExp('^' + nameRegexp + '$');
const getAllMatches = function(string, regex) {
const matches = [];
let match = regex.exec(string);
while (match) {
const allmatches = [];
allmatches.startIndex = regex.lastIndex - match[0].length;
const len = match.length;
for (let index = 0; index < len; index++) {
allmatches.push(match[index]);
}
matches.push(allmatches);
match = regex.exec(string);
}
return matches;
};
const isName = function(string) {
const match = regexName.exec(string);
return !(match === null || typeof match === 'undefined');
};
exports.isExist = function(v) {
return typeof v !== 'undefined';
};
exports.isEmptyObject = function(obj) {
return Object.keys(obj).length === 0;
};
/**
* Copy all the properties of a into b.
* @param {*} target
* @param {*} a
*/
exports.merge = function(target, a, arrayMode) {
if (a) {
const keys = Object.keys(a); // will return an array of own properties
const len = keys.length; //don't make it inline
for (let i = 0; i < len; i++) {
if (arrayMode === 'strict') {
target[keys[i]] = [ a[keys[i]] ];
} else {
target[keys[i]] = a[keys[i]];
}
}
}
};
/* exports.merge =function (b,a){
return Object.assign(b,a);
} */
exports.getValue = function(v) {
if (exports.isExist(v)) {
return v;
} else {
return '';
}
};
// const fakeCall = function(a) {return a;};
// const fakeCallNoReturn = function() {};
exports.buildOptions = function(options, defaultOptions, props) {
let newOptions = {};
if (!options) {
return defaultOptions; //if there are not options
}
for (let i = 0; i < props.length; i++) {
if (options[props[i]] !== undefined) {
newOptions[props[i]] = options[props[i]];
} else {
newOptions[props[i]] = defaultOptions[props[i]];
}
}
return newOptions;
};
/**
* Check if a tag name should be treated as array
*
* @param tagName the node tagname
* @param arrayMode the array mode option
* @param parentTagName the parent tag name
* @returns {boolean} true if node should be parsed as array
*/
exports.isTagNameInArrayMode = function (tagName, arrayMode, parentTagName) {
if (arrayMode === false) {
return false;
} else if (arrayMode instanceof RegExp) {
return arrayMode.test(tagName);
} else if (typeof arrayMode === 'function') {
return !!arrayMode(tagName, parentTagName);
}
return arrayMode === "strict";
}
exports.isName = isName;
exports.getAllMatches = getAllMatches;
exports.nameRegexp = nameRegexp;

413
node_modules/fast-xml-parser/src/validator.js generated vendored Normal file
View File

@@ -0,0 +1,413 @@
'use strict';
const util = require('./util');
const defaultOptions = {
allowBooleanAttributes: false, //A tag can have attributes without any value
};
const props = ['allowBooleanAttributes'];
//const tagsPattern = new RegExp("<\\/?([\\w:\\-_\.]+)\\s*\/?>","g");
exports.validate = function (xmlData, options) {
options = util.buildOptions(options, defaultOptions, props);
//xmlData = xmlData.replace(/(\r\n|\n|\r)/gm,"");//make it single line
//xmlData = xmlData.replace(/(^\s*<\?xml.*?\?>)/g,"");//Remove XML starting tag
//xmlData = xmlData.replace(/(<!DOCTYPE[\s\w\"\.\/\-\:]+(\[.*\])*\s*>)/g,"");//Remove DOCTYPE
const tags = [];
let tagFound = false;
//indicates that the root tag has been closed (aka. depth 0 has been reached)
let reachedRoot = false;
if (xmlData[0] === '\ufeff') {
// check for byte order mark (BOM)
xmlData = xmlData.substr(1);
}
for (let i = 0; i < xmlData.length; i++) {
if (xmlData[i] === '<' && xmlData[i+1] === '?') {
i+=2;
i = readPI(xmlData,i);
if (i.err) return i;
}else if (xmlData[i] === '<') {
//starting of tag
//read until you reach to '>' avoiding any '>' in attribute value
let tagStartPos = i;
i++;
if (xmlData[i] === '!') {
i = readCommentAndCDATA(xmlData, i);
continue;
} else {
let closingTag = false;
if (xmlData[i] === '/') {
//closing tag
closingTag = true;
i++;
}
//read tagname
let tagName = '';
for (; i < xmlData.length &&
xmlData[i] !== '>' &&
xmlData[i] !== ' ' &&
xmlData[i] !== '\t' &&
xmlData[i] !== '\n' &&
xmlData[i] !== '\r'; i++
) {
tagName += xmlData[i];
}
tagName = tagName.trim();
//console.log(tagName);
if (tagName[tagName.length - 1] === '/') {
//self closing tag without attributes
tagName = tagName.substring(0, tagName.length - 1);
//continue;
i--;
}
if (!validateTagName(tagName)) {
let msg;
if (tagName.trim().length === 0) {
msg = "Invalid space after '<'.";
} else {
msg = "Tag '"+tagName+"' is an invalid name.";
}
return getErrorObject('InvalidTag', msg, getLineNumberForPosition(xmlData, i));
}
const result = readAttributeStr(xmlData, i);
if (result === false) {
return getErrorObject('InvalidAttr', "Attributes for '"+tagName+"' have open quote.", getLineNumberForPosition(xmlData, i));
}
let attrStr = result.value;
i = result.index;
if (attrStr[attrStr.length - 1] === '/') {
//self closing tag
const attrStrStart = i - attrStr.length;
attrStr = attrStr.substring(0, attrStr.length - 1);
const isValid = validateAttributeString(attrStr, options);
if (isValid === true) {
tagFound = true;
//continue; //text may presents after self closing tag
} else {
//the result from the nested function returns the position of the error within the attribute
//in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute
//this gives us the absolute index in the entire xml, which we can use to find the line at last
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));
}
} else if (closingTag) {
if (!result.tagClosed) {
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' doesn't have proper closing.", getLineNumberForPosition(xmlData, i));
} else if (attrStr.trim().length > 0) {
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
} else {
const otg = tags.pop();
if (tagName !== otg.tagName) {
let openPos = getLineNumberForPosition(xmlData, otg.tagStartPos);
return getErrorObject('InvalidTag',
"Expected closing tag '"+otg.tagName+"' (opened in line "+openPos.line+", col "+openPos.col+") instead of closing tag '"+tagName+"'.",
getLineNumberForPosition(xmlData, tagStartPos));
}
//when there are no more tags, we reached the root level.
if (tags.length == 0) {
reachedRoot = true;
}
}
} else {
const isValid = validateAttributeString(attrStr, options);
if (isValid !== true) {
//the result from the nested function returns the position of the error within the attribute
//in order to get the 'true' error line, we need to calculate the position where the attribute begins (i - attrStr.length) and then add the position within the attribute
//this gives us the absolute index in the entire xml, which we can use to find the line at last
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, i - attrStr.length + isValid.err.line));
}
//if the root level has been reached before ...
if (reachedRoot === true) {
return getErrorObject('InvalidXml', 'Multiple possible root nodes found.', getLineNumberForPosition(xmlData, i));
} else {
tags.push({tagName, tagStartPos});
}
tagFound = true;
}
//skip tag text value
//It may include comments and CDATA value
for (i++; i < xmlData.length; i++) {
if (xmlData[i] === '<') {
if (xmlData[i + 1] === '!') {
//comment or CADATA
i++;
i = readCommentAndCDATA(xmlData, i);
continue;
} else if (xmlData[i+1] === '?') {
i = readPI(xmlData, ++i);
if (i.err) return i;
} else{
break;
}
} else if (xmlData[i] === '&') {
const afterAmp = validateAmpersand(xmlData, i);
if (afterAmp == -1)
return getErrorObject('InvalidChar', "char '&' is not expected.", getLineNumberForPosition(xmlData, i));
i = afterAmp;
}
} //end of reading tag text value
if (xmlData[i] === '<') {
i--;
}
}
} else {
if (xmlData[i] === ' ' || xmlData[i] === '\t' || xmlData[i] === '\n' || xmlData[i] === '\r') {
continue;
}
return getErrorObject('InvalidChar', "char '"+xmlData[i]+"' is not expected.", getLineNumberForPosition(xmlData, i));
}
}
if (!tagFound) {
return getErrorObject('InvalidXml', 'Start tag expected.', 1);
}else if (tags.length == 1) {
return getErrorObject('InvalidTag', "Unclosed tag '"+tags[0].tagName+"'.", getLineNumberForPosition(xmlData, tags[0].tagStartPos));
}else if (tags.length > 0) {
return getErrorObject('InvalidXml', "Invalid '"+
JSON.stringify(tags.map(t => t.tagName), null, 4).replace(/\r?\n/g, '')+
"' found.", {line: 1, col: 1});
}
return true;
};
/**
* Read Processing insstructions and skip
* @param {*} xmlData
* @param {*} i
*/
function readPI(xmlData, i) {
const start = i;
for (; i < xmlData.length; i++) {
if (xmlData[i] == '?' || xmlData[i] == ' ') {
//tagname
const tagname = xmlData.substr(start, i - start);
if (i > 5 && tagname === 'xml') {
return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));
} else if (xmlData[i] == '?' && xmlData[i + 1] == '>') {
//check if valid attribut string
i++;
break;
} else {
continue;
}
}
}
return i;
}
function readCommentAndCDATA(xmlData, i) {
if (xmlData.length > i + 5 && xmlData[i + 1] === '-' && xmlData[i + 2] === '-') {
//comment
for (i += 3; i < xmlData.length; i++) {
if (xmlData[i] === '-' && xmlData[i + 1] === '-' && xmlData[i + 2] === '>') {
i += 2;
break;
}
}
} else if (
xmlData.length > i + 8 &&
xmlData[i + 1] === 'D' &&
xmlData[i + 2] === 'O' &&
xmlData[i + 3] === 'C' &&
xmlData[i + 4] === 'T' &&
xmlData[i + 5] === 'Y' &&
xmlData[i + 6] === 'P' &&
xmlData[i + 7] === 'E'
) {
let angleBracketsCount = 1;
for (i += 8; i < xmlData.length; i++) {
if (xmlData[i] === '<') {
angleBracketsCount++;
} else if (xmlData[i] === '>') {
angleBracketsCount--;
if (angleBracketsCount === 0) {
break;
}
}
}
} else if (
xmlData.length > i + 9 &&
xmlData[i + 1] === '[' &&
xmlData[i + 2] === 'C' &&
xmlData[i + 3] === 'D' &&
xmlData[i + 4] === 'A' &&
xmlData[i + 5] === 'T' &&
xmlData[i + 6] === 'A' &&
xmlData[i + 7] === '['
) {
for (i += 8; i < xmlData.length; i++) {
if (xmlData[i] === ']' && xmlData[i + 1] === ']' && xmlData[i + 2] === '>') {
i += 2;
break;
}
}
}
return i;
}
const doubleQuote = '"';
const singleQuote = "'";
/**
* Keep reading xmlData until '<' is found outside the attribute value.
* @param {string} xmlData
* @param {number} i
*/
function readAttributeStr(xmlData, i) {
let attrStr = '';
let startChar = '';
let tagClosed = false;
for (; i < xmlData.length; i++) {
if (xmlData[i] === doubleQuote || xmlData[i] === singleQuote) {
if (startChar === '') {
startChar = xmlData[i];
} else if (startChar !== xmlData[i]) {
//if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa
} else {
startChar = '';
}
} else if (xmlData[i] === '>') {
if (startChar === '') {
tagClosed = true;
break;
}
}
attrStr += xmlData[i];
}
if (startChar !== '') {
return false;
}
return {
value: attrStr,
index: i,
tagClosed: tagClosed
};
}
/**
* Select all the attributes whether valid or invalid.
*/
const validAttrStrRegxp = new RegExp('(\\s*)([^\\s=]+)(\\s*=)?(\\s*([\'"])(([\\s\\S])*?)\\5)?', 'g');
//attr, ="sd", a="amit's", a="sd"b="saf", ab cd=""
function validateAttributeString(attrStr, options) {
//console.log("start:"+attrStr+":end");
//if(attrStr.trim().length === 0) return true; //empty string
const matches = util.getAllMatches(attrStr, validAttrStrRegxp);
const attrNames = {};
for (let i = 0; i < matches.length; i++) {
if (matches[i][1].length === 0) {
//nospace before attribute name: a="sd"b="saf"
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(matches[i]))
} else if (matches[i][3] === undefined && !options.allowBooleanAttributes) {
//independent attribute: ab
return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i]));
}
/* else if(matches[i][6] === undefined){//attribute without value: ab=
return { err: { code:"InvalidAttr",msg:"attribute " + matches[i][2] + " has no value assigned."}};
} */
const attrName = matches[i][2];
if (!validateAttrName(attrName)) {
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i]));
}
if (!attrNames.hasOwnProperty(attrName)) {
//check for duplicate attribute.
attrNames[attrName] = 1;
} else {
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i]));
}
}
return true;
}
function validateNumberAmpersand(xmlData, i) {
let re = /\d/;
if (xmlData[i] === 'x') {
i++;
re = /[\da-fA-F]/;
}
for (; i < xmlData.length; i++) {
if (xmlData[i] === ';')
return i;
if (!xmlData[i].match(re))
break;
}
return -1;
}
function validateAmpersand(xmlData, i) {
// https://www.w3.org/TR/xml/#dt-charref
i++;
if (xmlData[i] === ';')
return -1;
if (xmlData[i] === '#') {
i++;
return validateNumberAmpersand(xmlData, i);
}
let count = 0;
for (; i < xmlData.length; i++, count++) {
if (xmlData[i].match(/\w/) && count < 20)
continue;
if (xmlData[i] === ';')
break;
return -1;
}
return i;
}
function getErrorObject(code, message, lineNumber) {
return {
err: {
code: code,
msg: message,
line: lineNumber.line || lineNumber,
col: lineNumber.col,
},
};
}
function validateAttrName(attrName) {
return util.isName(attrName);
}
// const startsWithXML = /^xml/i;
function validateTagName(tagname) {
return util.isName(tagname) /* && !tagname.match(startsWithXML) */;
}
//this function returns the line number for the character at the given index
function getLineNumberForPosition(xmlData, index) {
const lines = xmlData.substring(0, index).split(/\r?\n/);
return {
line: lines.length,
// column number is last line's length + 1, because column numbering starts at 1:
col: lines[lines.length - 1].length + 1
};
}
//this function returns the position of the first character of match within attrStr
function getPositionFromMatch(match) {
return match.startIndex + match[1].length;
}

17
node_modules/fast-xml-parser/src/xmlNode.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
'use strict';
module.exports = function(tagname, parent, val) {
this.tagname = tagname;
this.parent = parent;
this.child = {}; //child tags
this.attrsMap = {}; //attributes map
this.val = val; //text only
this.addChild = function(child) {
if (Array.isArray(this.child[child.tagname])) {
//already presents
this.child[child.tagname].push(child);
} else {
this.child[child.tagname] = [child];
}
};
};

339
node_modules/fast-xml-parser/src/xmlstr2xmlnode.js generated vendored Normal file
View File

@@ -0,0 +1,339 @@
'use strict';
const util = require('./util');
const buildOptions = require('./util').buildOptions;
const xmlNode = require('./xmlNode');
const toNumber = require("strnum");
const regx =
'<((!\\[CDATA\\[([\\s\\S]*?)(]]>))|((NAME:)?(NAME))([^>]*)>|((\\/)(NAME)\\s*>))([^<]*)'
.replace(/NAME/g, util.nameRegexp);
//const tagsRegx = new RegExp("<(\\/?[\\w:\\-\._]+)([^>]*)>(\\s*"+cdataRegx+")*([^<]+)?","g");
//const tagsRegx = new RegExp("<(\\/?)((\\w*:)?([\\w:\\-\._]+))([^>]*)>([^<]*)("+cdataRegx+"([^<]*))*([^<]+)?","g");
//polyfill
if (!Number.parseInt && window.parseInt) {
Number.parseInt = window.parseInt;
}
if (!Number.parseFloat && window.parseFloat) {
Number.parseFloat = window.parseFloat;
}
const defaultOptions = {
attributeNamePrefix: '@_',
attrNodeName: false,
textNodeName: '#text',
ignoreAttributes: true,
ignoreNameSpace: false,
allowBooleanAttributes: false, //a tag can have attributes without any value
//ignoreRootElement : false,
parseNodeValue: true,
parseAttributeValue: false,
arrayMode: false,
trimValues: true, //Trim string values of tag and attributes
cdataTagName: false,
cdataPositionChar: '\\c',
numParseOptions: {
hex: true,
leadingZeros: true
},
tagValueProcessor: function(a, tagName) {
return a;
},
attrValueProcessor: function(a, attrName) {
return a;
},
stopNodes: [],
alwaysCreateTextNode: false
//decodeStrict: false,
};
exports.defaultOptions = defaultOptions;
const props = [
'attributeNamePrefix',
'attrNodeName',
'textNodeName',
'ignoreAttributes',
'ignoreNameSpace',
'allowBooleanAttributes',
'parseNodeValue',
'parseAttributeValue',
'arrayMode',
'trimValues',
'cdataTagName',
'cdataPositionChar',
'tagValueProcessor',
'attrValueProcessor',
'parseTrueNumberOnly',
'numParseOptions',
'stopNodes',
'alwaysCreateTextNode'
];
exports.props = props;
/**
* Trim -> valueProcessor -> parse value
* @param {string} tagName
* @param {string} val
* @param {object} options
*/
function processTagValue(tagName, val, options) {
if (val) {
if (options.trimValues) {
val = val.trim();
}
val = options.tagValueProcessor(val, tagName);
val = parseValue(val, options.parseNodeValue, options.numParseOptions);
}
return val;
}
function resolveNameSpace(tagname, options) {
if (options.ignoreNameSpace) {
const tags = tagname.split(':');
const prefix = tagname.charAt(0) === '/' ? '/' : '';
if (tags[0] === 'xmlns') {
return '';
}
if (tags.length === 2) {
tagname = prefix + tags[1];
}
}
return tagname;
}
function parseValue(val, shouldParse, options) {
if (shouldParse && typeof val === 'string') {
//console.log(options)
const newval = val.trim();
if(newval === 'true' ) return true;
else if(newval === 'false' ) return false;
else return toNumber(val, options);
} else {
if (util.isExist(val)) {
return val;
} else {
return '';
}
}
}
//TODO: change regex to capture NS
//const attrsRegx = new RegExp("([\\w\\-\\.\\:]+)\\s*=\\s*(['\"])((.|\n)*?)\\2","gm");
const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])(.*?)\\3)?', 'g');
function buildAttributesMap(attrStr, options) {
if (!options.ignoreAttributes && typeof attrStr === 'string') {
attrStr = attrStr.replace(/\r?\n/g, ' ');
//attrStr = attrStr || attrStr.trim();
const matches = util.getAllMatches(attrStr, attrsRegx);
const len = matches.length; //don't make it inline
const attrs = {};
for (let i = 0; i < len; i++) {
const attrName = resolveNameSpace(matches[i][1], options);
if (attrName.length) {
if (matches[i][4] !== undefined) {
if (options.trimValues) {
matches[i][4] = matches[i][4].trim();
}
matches[i][4] = options.attrValueProcessor(matches[i][4], attrName);
attrs[options.attributeNamePrefix + attrName] = parseValue(
matches[i][4],
options.parseAttributeValue,
options.numParseOptions
);
} else if (options.allowBooleanAttributes) {
attrs[options.attributeNamePrefix + attrName] = true;
}
}
}
if (!Object.keys(attrs).length) {
return;
}
if (options.attrNodeName) {
const attrCollection = {};
attrCollection[options.attrNodeName] = attrs;
return attrCollection;
}
return attrs;
}
}
const getTraversalObj = function(xmlData, options) {
xmlData = xmlData.replace(/\r\n?/g, "\n");
options = buildOptions(options, defaultOptions, props);
const xmlObj = new xmlNode('!xml');
let currentNode = xmlObj;
let textData = "";
//function match(xmlData){
for(let i=0; i< xmlData.length; i++){
const ch = xmlData[i];
if(ch === '<'){
if( xmlData[i+1] === '/') {//Closing Tag
const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.")
let tagName = xmlData.substring(i+2,closeIndex).trim();
if(options.ignoreNameSpace){
const colonIndex = tagName.indexOf(":");
if(colonIndex !== -1){
tagName = tagName.substr(colonIndex+1);
}
}
/* if (currentNode.parent) {
currentNode.parent.val = util.getValue(currentNode.parent.val) + '' + processTagValue2(tagName, textData , options);
} */
if(currentNode){
if(currentNode.val){
currentNode.val = util.getValue(currentNode.val) + '' + processTagValue(tagName, textData , options);
}else{
currentNode.val = processTagValue(tagName, textData , options);
}
}
if (options.stopNodes.length && options.stopNodes.includes(currentNode.tagname)) {
currentNode.child = []
if (currentNode.attrsMap == undefined) { currentNode.attrsMap = {}}
currentNode.val = xmlData.substr(currentNode.startIndex + 1, i - currentNode.startIndex - 1)
}
currentNode = currentNode.parent;
textData = "";
i = closeIndex;
} else if( xmlData[i+1] === '?') {
i = findClosingIndex(xmlData, "?>", i, "Pi Tag is not closed.")
} else if(xmlData.substr(i + 1, 3) === '!--') {
i = findClosingIndex(xmlData, "-->", i, "Comment is not closed.")
} else if( xmlData.substr(i + 1, 2) === '!D') {
const closeIndex = findClosingIndex(xmlData, ">", i, "DOCTYPE is not closed.")
const tagExp = xmlData.substring(i, closeIndex);
if(tagExp.indexOf("[") >= 0){
i = xmlData.indexOf("]>", i) + 1;
}else{
i = closeIndex;
}
}else if(xmlData.substr(i + 1, 2) === '![') {
const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2
const tagExp = xmlData.substring(i + 9,closeIndex);
//considerations
//1. CDATA will always have parent node
//2. A tag with CDATA is not a leaf node so it's value would be string type.
if(textData){
currentNode.val = util.getValue(currentNode.val) + '' + processTagValue(currentNode.tagname, textData , options);
textData = "";
}
if (options.cdataTagName) {
//add cdata node
const childNode = new xmlNode(options.cdataTagName, currentNode, tagExp);
currentNode.addChild(childNode);
//for backtracking
currentNode.val = util.getValue(currentNode.val) + options.cdataPositionChar;
//add rest value to parent node
if (tagExp) {
childNode.val = tagExp;
}
} else {
currentNode.val = (currentNode.val || '') + (tagExp || '');
}
i = closeIndex + 2;
}else {//Opening tag
const result = closingIndexForOpeningTag(xmlData, i+1)
let tagExp = result.data;
const closeIndex = result.index;
const separatorIndex = tagExp.indexOf(" ");
let tagName = tagExp;
let shouldBuildAttributesMap = true;
if(separatorIndex !== -1){
tagName = tagExp.substr(0, separatorIndex).replace(/\s\s*$/, '');
tagExp = tagExp.substr(separatorIndex + 1);
}
if(options.ignoreNameSpace){
const colonIndex = tagName.indexOf(":");
if(colonIndex !== -1){
tagName = tagName.substr(colonIndex+1);
shouldBuildAttributesMap = tagName !== result.data.substr(colonIndex + 1);
}
}
//save text to parent node
if (currentNode && textData) {
if(currentNode.tagname !== '!xml'){
currentNode.val = util.getValue(currentNode.val) + '' + processTagValue( currentNode.tagname, textData, options);
}
}
if(tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1){//selfClosing tag
if(tagName[tagName.length - 1] === "/"){ //remove trailing '/'
tagName = tagName.substr(0, tagName.length - 1);
tagExp = tagName;
}else{
tagExp = tagExp.substr(0, tagExp.length - 1);
}
const childNode = new xmlNode(tagName, currentNode, '');
if(tagName !== tagExp){
childNode.attrsMap = buildAttributesMap(tagExp, options);
}
currentNode.addChild(childNode);
}else{//opening tag
const childNode = new xmlNode( tagName, currentNode );
if (options.stopNodes.length && options.stopNodes.includes(childNode.tagname)) {
childNode.startIndex=closeIndex;
}
if(tagName !== tagExp && shouldBuildAttributesMap){
childNode.attrsMap = buildAttributesMap(tagExp, options);
}
currentNode.addChild(childNode);
currentNode = childNode;
}
textData = "";
i = closeIndex;
}
}else{
textData += xmlData[i];
}
}
return xmlObj;
}
function closingIndexForOpeningTag(data, i){
let attrBoundary;
let tagExp = "";
for (let index = i; index < data.length; index++) {
let ch = data[index];
if (attrBoundary) {
if (ch === attrBoundary) attrBoundary = "";//reset
} else if (ch === '"' || ch === "'") {
attrBoundary = ch;
} else if (ch === '>') {
return {
data: tagExp,
index: index
}
} else if (ch === '\t') {
ch = " "
}
tagExp += ch;
}
}
function findClosingIndex(xmlData, str, i, errMsg){
const closingIndex = xmlData.indexOf(str, i);
if(closingIndex === -1){
throw new Error(errMsg)
}else{
return closingIndex + str.length - 1;
}
}
exports.getTraversalObj = getTraversalObj;