Socket
Socket
Sign inDemoInstall

fast-xml-parser

Package Overview
Dependencies
Maintainers
1
Versions
136
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fast-xml-parser - npm Package Compare versions

Comparing version 3.20.3 to 3.21.0

12

package.json
{
"name": "fast-xml-parser",
"version": "3.20.3",
"version": "3.21.0",
"description": "Validate XML or Parse XML to JS/JSON very fast without C/C++ based libraries",
"main": "./src/parser.js",
"scripts": {
"test": "jasmine spec/*spec.js",
"test": "npx nyc jasmine spec/*spec.js",
"unit": "jasmine",
"coverage": "npx nyc report --reporter html --reporter text -t .nyc_output --report-dir .nyc_output/summary",
"perf": "node ./benchmark/perfTest3.js",
"lint": "eslint src/*.js spec/*.js",
"bundle": "webpack && webpack --config webpack-prod.config.js",
"coverage": "istanbul cover -x \"cli.js\" -x \"spec/*spec.js\" jasmine spec/*spec.js;",
"coverage:check": "istanbul check-coverage --branch 90 --statement 90",
"prettier": "prettier --write src/**/*.js",
"publish-please": "publish-please",
"prepublishOnly": "publish-please guard"
"checkReadiness": "publish-please --dry-run"
},

@@ -79,4 +78,2 @@ "bin": {

"he": "^1.2.0",
"http-server": "^0.12.3",
"istanbul": "^0.4.5",
"jasmine": "^3.6.4",

@@ -95,4 +92,5 @@ "nimnjs": "^1.3.2",

"dependencies": {
"nyc": "^15.1.0",
"strnum": "^1.0.4"
}
}

@@ -26,2 +26,4 @@

Check [ThankYouBackers](https://github.com/NaturalIntelligence/ThankYouBackers) for our contributors
## Users

@@ -107,9 +109,15 @@ List of some applications/projects using Fast XML Parser. (Raise an issue to submit yours)

To use it in **NPM package** install it first
### Installation
`$npm install fast-xml-parser` or using [yarn](https://yarnpkg.com/) `$yarn add fast-xml-parser`
To use it as an **NPM package**:
`npm install fast-xml-parser`
Or using [yarn](https://yarnpkg.com/):
`yarn add fast-xml-parser`
To use it from a **CLI** install it globally with the `-g` option.
`$npm install fast-xml-parser -g`
`npm install fast-xml-parser -g`

@@ -122,10 +130,10 @@ To use it on a **webpage** include it from a [CDN](https://cdnjs.com/libraries/fast-xml-parser)

```js
var jsonObj = parser.parse(xmlData [,options] );
const jsonObj = parser.parse(xmlData [,options] );
```
```js
var parser = require('fast-xml-parser');
var he = require('he');
const parser = require('fast-xml-parser');
const he = require('he');
var options = {
const options = {
attributeNamePrefix : "@_",

@@ -147,16 +155,17 @@ attrNodeName: "attr", //default is 'false'

//skipLike: /\+[0-9]{10}/
}
},
arrayMode: false, //"strict"
attrValueProcessor: (val, attrName) => he.decode(val, {isAttributeValue: true}),//default is a=>a
tagValueProcessor : (val, tagName) => he.decode(val), //default is a=>a
stopNodes: ["parse-me-as-string"]
stopNodes: ["parse-me-as-string"],
alwaysCreateTextNode: false
};
if( parser.validate(xmlData) === true) { //optional (it'll return an object in case it's not valid)
var jsonObj = parser.parse(xmlData,options);
let jsonObj = parser.parse(xmlData,options);
}
// Intermediate obj
var tObj = parser.getTraversalObj(xmlData,options);
var jsonObj = parser.convertToJson(tObj,options);
const tObj = parser.getTraversalObj(xmlData,options);
let jsonObj = parser.convertToJson(tObj,options);

@@ -168,3 +177,3 @@ ```

try{
var jsonObj = parser.parse(xmlData,options, true);
let jsonObj = parser.parse(xmlData,options, true);
}catch(error){

@@ -208,3 +217,3 @@ console.log(error.message)

* **stopNodes** : an array of tag names which are not required to be parsed. Instead their values are parsed as string.
* **alwaysCreateTextNode** : When `true`, forces the parser always return a property for the `textNodeName` even if there are no attributes or node children.
</details>

@@ -232,5 +241,5 @@

```js
var result = parser.validate(xmlData);
const result = parser.validate(xmlData);
if (result !== true) console.log(result.err);
var jsonObj = parser.parse(xmlData);
const jsonObj = parser.parse(xmlData);
```

@@ -242,5 +251,5 @@ </details>

```js
var Parser = require("fast-xml-parser").j2xParser;
const Parser = require("fast-xml-parser").j2xParser;
//default options need not to set
var defaultOptions = {
const defaultOptions = {
attributeNamePrefix : "@_",

@@ -256,6 +265,7 @@ attrNodeName: "@", //default is false

tagValueProcessor: a=> he.encode(a, { useNamedReferences: true}),// default is a=>a
attrValueProcessor: a=> he.encode(a, {isAttributeValue: isAttribute, useNamedReferences: true})// default is a=>a
attrValueProcessor: a=> he.encode(a, {isAttributeValue: isAttribute, useNamedReferences: true}),// default is a=>a
rootNodeName: "element"
};
var parser = new Parser(defaultOptions);
var xml = parser.parse(json_or_js_obj);
const parser = new Parser(defaultOptions);
const xml = parser.parse(json_or_js_obj);
```

@@ -279,2 +289,3 @@

* **attrValueProcessor** : Process attribute value during transformation. Like HTML encoding, word capitalization, etc. Applicable in case of string only.
* **rootNodeName** : When input js object is array, parser uses array index by default as tag name. You can set this property for proper response.
</details>

@@ -281,0 +292,0 @@

@@ -35,2 +35,3 @@ 'use strict';

'attrValueProcessor',
'rootNodeName', //when array as root
];

@@ -83,2 +84,7 @@

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;

@@ -85,0 +91,0 @@ };

@@ -51,3 +51,3 @@ 'use strict';

const itemSchema = e_schema[0];
//var itemSchemaType = itemSchema;
//const itemSchemaType = itemSchema;
const arr_len = node.length;

@@ -54,0 +54,0 @@

@@ -22,6 +22,6 @@ 'use strict';

for (let index = 0; index < keys.length; index++) {
var tagname = keys[index];
const tagname = keys[index];
if (node.child[tagname] && node.child[tagname].length > 1) {
jObj += '"' + tagname + '" : [ ';
for (var tag in node.child[tagname]) {
for (let tag in node.child[tagname]) {
jObj += _cToJsonStr(node.child[tagname][tag], options) + ' , ';

@@ -28,0 +28,0 @@ }

@@ -9,3 +9,3 @@ 'use strict';

// when no child node or attr is present
if ((!node.child || util.isEmptyObject(node.child)) && (!node.attrsMap || util.isEmptyObject(node.attrsMap))) {
if (!options.alwaysCreateTextNode && (!node.child || util.isEmptyObject(node.child)) && (!node.attrsMap || util.isEmptyObject(node.attrsMap))) {
return util.isExist(node.val) ? node.val : '';

@@ -12,0 +12,0 @@ }

@@ -19,2 +19,3 @@ type X2jOptions = {

stopNodes: string[];
alwaysCreateTextNode: boolean;
};

@@ -49,3 +50,3 @@ type strnumOptions = {

type ValidationError = {
err: { code: string; msg: string, line: number };
err: { code: string; msg: string, line: number, col: number };
};

@@ -52,0 +53,0 @@

@@ -13,2 +13,3 @@ 'use strict';

const allmatches = [];
allmatches.startIndex = regex.lastIndex - match[0].length;
const len = match.length;

@@ -71,3 +72,3 @@ for (let index = 0; index < len; index++) {

exports.buildOptions = function(options, defaultOptions, props) {
var newOptions = {};
let newOptions = {};
if (!options) {

@@ -74,0 +75,0 @@ return defaultOptions; //if there are not options

@@ -38,3 +38,3 @@ 'use strict';

//read until you reach to '>' avoiding any '>' in attribute value
let tagStartPos = i;
i++;

@@ -75,3 +75,3 @@

if (tagName.trim().length === 0) {
msg = "There is an unnecessary space between tag name and backward slash '</ ..'.";
msg = "Invalid space after '<'.";
} else {

@@ -92,2 +92,3 @@ msg = "Tag '"+tagName+"' is an invalid name.";

//self closing tag
const attrStrStart = i - attrStr.length;
attrStr = attrStr.substring(0, attrStr.length - 1);

@@ -102,3 +103,3 @@ const isValid = validateAttributeString(attrStr, options);

//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));
return getErrorObject(isValid.err.code, isValid.err.msg, getLineNumberForPosition(xmlData, attrStrStart + isValid.err.line));
}

@@ -109,7 +110,10 @@ } else if (closingTag) {

} else if (attrStr.trim().length > 0) {
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, i));
return getErrorObject('InvalidTag', "Closing tag '"+tagName+"' can't have attributes or invalid starting.", getLineNumberForPosition(xmlData, tagStartPos));
} else {
const otg = tags.pop();
if (tagName !== otg) {
return getErrorObject('InvalidTag', "Closing tag '"+otg+"' is expected inplace of '"+tagName+"'.", getLineNumberForPosition(xmlData, i));
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));
}

@@ -135,3 +139,3 @@

} else {
tags.push(tagName);
tags.push({tagName, tagStartPos});
}

@@ -177,4 +181,8 @@ tagFound = true;

return getErrorObject('InvalidXml', 'Start tag expected.', 1);
} else if (tags.length > 0) {
return getErrorObject('InvalidXml', "Invalid '"+JSON.stringify(tags, null, 4).replace(/\r?\n/g, '')+"' found.", 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});
}

@@ -191,7 +199,7 @@

function readPI(xmlData, i) {
var start = i;
const start = i;
for (; i < xmlData.length; i++) {
if (xmlData[i] == '?' || xmlData[i] == ' ') {
//tagname
var tagname = xmlData.substr(start, i - start);
const tagname = xmlData.substr(start, i - start);
if (i > 5 && tagname === 'xml') {

@@ -262,4 +270,4 @@ return getErrorObject('InvalidXml', 'XML declaration allowed only at the start of the document.', getLineNumberForPosition(xmlData, i));

var doubleQuote = '"';
var singleQuote = "'";
const doubleQuote = '"';
const singleQuote = "'";

@@ -281,3 +289,2 @@ /**

//if vaue is enclosed with double quote then single quotes are allowed inside the value and vice versa
continue;
} else {

@@ -323,6 +330,6 @@ startChar = '';

//nospace before attribute name: a="sd"b="saf"
return getErrorObject('InvalidAttr', "Attribute '"+matches[i][2]+"' has no space in starting.", getPositionFromMatch(attrStr, matches[i][0]))
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(attrStr, matches[i][0]));
return getErrorObject('InvalidAttr', "boolean attribute '"+matches[i][2]+"' is not allowed.", getPositionFromMatch(matches[i]));
}

@@ -334,3 +341,3 @@ /* else if(matches[i][6] === undefined){//attribute without value: ab=

if (!validateAttrName(attrName)) {
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(attrStr, matches[i][0]));
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is an invalid name.", getPositionFromMatch(matches[i]));
}

@@ -341,3 +348,3 @@ if (!attrNames.hasOwnProperty(attrName)) {

} else {
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(attrStr, matches[i][0]));
return getErrorObject('InvalidAttr', "Attribute '"+attrName+"' is repeated.", getPositionFromMatch(matches[i]));
}

@@ -389,3 +396,4 @@ }

msg: message,
line: lineNumber,
line: lineNumber.line || lineNumber,
col: lineNumber.col,
},

@@ -407,9 +415,14 @@ };

function getLineNumberForPosition(xmlData, index) {
var lines = xmlData.substring(0, index).split(/\r?\n/);
return lines.length;
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 last character of match within attrStr
function getPositionFromMatch(attrStr, match) {
return attrStr.indexOf(match) + match.length;
//this function returns the position of the first character of match within attrStr
function getPositionFromMatch(match) {
return match.startIndex + match[1].length;
}

@@ -47,3 +47,4 @@ 'use strict';

},
stopNodes: []
stopNodes: [],
alwaysCreateTextNode: false
//decodeStrict: false,

@@ -71,3 +72,4 @@ };

'numParseOptions',
'stopNodes'
'stopNodes',
'alwaysCreateTextNode'
];

@@ -74,0 +76,0 @@ exports.props = props;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc