ubdate
This commit is contained in:
280
node_modules/fast-xml-parser/src/json2xml.js
generated
vendored
Normal file
280
node_modules/fast-xml-parser/src/json2xml.js
generated
vendored
Normal 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
144
node_modules/fast-xml-parser/src/nimndata.js
generated
vendored
Normal 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
42
node_modules/fast-xml-parser/src/node2json.js
generated
vendored
Normal 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
63
node_modules/fast-xml-parser/src/node2json_str.js
generated
vendored
Normal 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
79
node_modules/fast-xml-parser/src/parser.d.ts
generated
vendored
Normal 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
76
node_modules/fast-xml-parser/src/parser.js
generated
vendored
Normal 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
92
node_modules/fast-xml-parser/src/read.js
generated
vendored
Normal 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
108
node_modules/fast-xml-parser/src/util.js
generated
vendored
Normal 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
413
node_modules/fast-xml-parser/src/validator.js
generated
vendored
Normal 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
17
node_modules/fast-xml-parser/src/xmlNode.js
generated
vendored
Normal 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
339
node_modules/fast-xml-parser/src/xmlstr2xmlnode.js
generated
vendored
Normal 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;
|
||||
Reference in New Issue
Block a user