@depup/fast-xml-parser 5.5.6-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +752 -0
  2. package/LICENSE +21 -0
  3. package/README.md +31 -0
  4. package/changes.json +10 -0
  5. package/lib/fxbuilder.min.js +2 -0
  6. package/lib/fxbuilder.min.js.map +1 -0
  7. package/lib/fxp.cjs +1 -0
  8. package/lib/fxp.d.cts +595 -0
  9. package/lib/fxp.min.js +2 -0
  10. package/lib/fxp.min.js.map +1 -0
  11. package/lib/fxparser.min.js +2 -0
  12. package/lib/fxparser.min.js.map +1 -0
  13. package/lib/fxvalidator.min.js +2 -0
  14. package/lib/fxvalidator.min.js.map +1 -0
  15. package/package.json +112 -0
  16. package/src/cli/cli.js +97 -0
  17. package/src/cli/man.js +17 -0
  18. package/src/cli/read.js +43 -0
  19. package/src/fxp.d.ts +577 -0
  20. package/src/fxp.js +14 -0
  21. package/src/ignoreAttributes.js +18 -0
  22. package/src/util.js +61 -0
  23. package/src/v6/CharsSymbol.js +16 -0
  24. package/src/v6/EntitiesParser.js +106 -0
  25. package/src/v6/OptionsBuilder.js +61 -0
  26. package/src/v6/OutputBuilders/BaseOutputBuilder.js +69 -0
  27. package/src/v6/OutputBuilders/JsArrBuilder.js +103 -0
  28. package/src/v6/OutputBuilders/JsMinArrBuilder.js +100 -0
  29. package/src/v6/OutputBuilders/JsObjBuilder.js +154 -0
  30. package/src/v6/OutputBuilders/ParserOptionsBuilder.js +94 -0
  31. package/src/v6/Report.js +0 -0
  32. package/src/v6/TagPath.js +81 -0
  33. package/src/v6/TagPathMatcher.js +13 -0
  34. package/src/v6/XMLParser.js +83 -0
  35. package/src/v6/Xml2JsParser.js +235 -0
  36. package/src/v6/XmlPartReader.js +210 -0
  37. package/src/v6/XmlSpecialTagsReader.js +111 -0
  38. package/src/v6/inputSource/BufferSource.js +116 -0
  39. package/src/v6/inputSource/StringSource.js +121 -0
  40. package/src/v6/valueParsers/EntitiesParser.js +105 -0
  41. package/src/v6/valueParsers/booleanParser.js +22 -0
  42. package/src/v6/valueParsers/booleanParserExt.js +19 -0
  43. package/src/v6/valueParsers/currency.js +38 -0
  44. package/src/v6/valueParsers/join.js +13 -0
  45. package/src/v6/valueParsers/number.js +14 -0
  46. package/src/v6/valueParsers/trim.js +6 -0
  47. package/src/validator.js +425 -0
  48. package/src/xmlbuilder/json2xml.js +6 -0
  49. package/src/xmlparser/DocTypeReader.js +401 -0
  50. package/src/xmlparser/OptionsBuilder.js +159 -0
  51. package/src/xmlparser/OrderedObjParser.js +905 -0
  52. package/src/xmlparser/XMLParser.js +71 -0
  53. package/src/xmlparser/node2json.js +174 -0
  54. package/src/xmlparser/xmlNode.js +40 -0
@@ -0,0 +1,71 @@
1
+ import { buildOptions } from './OptionsBuilder.js';
2
+ import OrderedObjParser from './OrderedObjParser.js';
3
+ import prettify from './node2json.js';
4
+ import { validate } from "../validator.js";
5
+ import XmlNode from './xmlNode.js';
6
+
7
+ export default class XMLParser {
8
+
9
+ constructor(options) {
10
+ this.externalEntities = {};
11
+ this.options = buildOptions(options);
12
+
13
+ }
14
+ /**
15
+ * Parse XML dats to JS object
16
+ * @param {string|Uint8Array} xmlData
17
+ * @param {boolean|Object} validationOption
18
+ */
19
+ parse(xmlData, validationOption) {
20
+ if (typeof xmlData !== "string" && xmlData.toString) {
21
+ xmlData = xmlData.toString();
22
+ } else if (typeof xmlData !== "string") {
23
+ throw new Error("XML data is accepted in String or Bytes[] form.")
24
+ }
25
+
26
+ if (validationOption) {
27
+ if (validationOption === true) validationOption = {}; //validate with default options
28
+
29
+ const result = validate(xmlData, validationOption);
30
+ if (result !== true) {
31
+ throw Error(`${result.err.msg}:${result.err.line}:${result.err.col}`)
32
+ }
33
+ }
34
+ const orderedObjParser = new OrderedObjParser(this.options);
35
+ orderedObjParser.addExternalEntities(this.externalEntities);
36
+ const orderedResult = orderedObjParser.parseXml(xmlData);
37
+ if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;
38
+ else return prettify(orderedResult, this.options, orderedObjParser.matcher);
39
+ }
40
+
41
+ /**
42
+ * Add Entity which is not by default supported by this library
43
+ * @param {string} key
44
+ * @param {string} value
45
+ */
46
+ addEntity(key, value) {
47
+ if (value.indexOf("&") !== -1) {
48
+ throw new Error("Entity value can't have '&'")
49
+ } else if (key.indexOf("&") !== -1 || key.indexOf(";") !== -1) {
50
+ throw new Error("An entity must be set without '&' and ';'. Eg. use '#xD' for '
'")
51
+ } else if (value === "&") {
52
+ throw new Error("An entity with value '&' is not permitted");
53
+ } else {
54
+ this.externalEntities[key] = value;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Returns a Symbol that can be used to access the metadata
60
+ * property on a node.
61
+ *
62
+ * If Symbol is not available in the environment, an ordinary property is used
63
+ * and the name of the property is here returned.
64
+ *
65
+ * The XMLMetaData property is only present when `captureMetaData`
66
+ * is true in the options.
67
+ */
68
+ static getMetaDataSymbol() {
69
+ return XmlNode.getMetaDataSymbol();
70
+ }
71
+ }
@@ -0,0 +1,174 @@
1
+ 'use strict';
2
+
3
+ import XmlNode from './xmlNode.js';
4
+ import { Matcher } from 'path-expression-matcher';
5
+
6
+ const METADATA_SYMBOL = XmlNode.getMetaDataSymbol();
7
+
8
+ /**
9
+ * Helper function to strip attribute prefix from attribute map
10
+ * @param {object} attrs - Attributes with prefix (e.g., {"@_class": "code"})
11
+ * @param {string} prefix - Attribute prefix to remove (e.g., "@_")
12
+ * @returns {object} Attributes without prefix (e.g., {"class": "code"})
13
+ */
14
+ function stripAttributePrefix(attrs, prefix) {
15
+ if (!attrs || typeof attrs !== 'object') return {};
16
+ if (!prefix) return attrs;
17
+
18
+ const rawAttrs = {};
19
+ for (const key in attrs) {
20
+ if (key.startsWith(prefix)) {
21
+ const rawName = key.substring(prefix.length);
22
+ rawAttrs[rawName] = attrs[key];
23
+ } else {
24
+ // Attribute without prefix (shouldn't normally happen, but be safe)
25
+ rawAttrs[key] = attrs[key];
26
+ }
27
+ }
28
+ return rawAttrs;
29
+ }
30
+
31
+ /**
32
+ *
33
+ * @param {array} node
34
+ * @param {any} options
35
+ * @param {Matcher} matcher - Path matcher instance
36
+ * @returns
37
+ */
38
+ export default function prettify(node, options, matcher) {
39
+ return compress(node, options, matcher);
40
+ }
41
+
42
+ /**
43
+ *
44
+ * @param {array} arr
45
+ * @param {object} options
46
+ * @param {Matcher} matcher - Path matcher instance
47
+ * @returns object
48
+ */
49
+ function compress(arr, options, matcher) {
50
+ let text;
51
+ const compressedObj = {}; //This is intended to be a plain object
52
+ for (let i = 0; i < arr.length; i++) {
53
+ const tagObj = arr[i];
54
+ const property = propName(tagObj);
55
+
56
+ // Push current property to matcher WITH RAW ATTRIBUTES (no prefix)
57
+ if (property !== undefined && property !== options.textNodeName) {
58
+ const rawAttrs = stripAttributePrefix(
59
+ tagObj[":@"] || {},
60
+ options.attributeNamePrefix
61
+ );
62
+ matcher.push(property, rawAttrs);
63
+ }
64
+
65
+ if (property === options.textNodeName) {
66
+ if (text === undefined) text = tagObj[property];
67
+ else text += "" + tagObj[property];
68
+ } else if (property === undefined) {
69
+ continue;
70
+ } else if (tagObj[property]) {
71
+
72
+ let val = compress(tagObj[property], options, matcher);
73
+ const isLeaf = isLeafTag(val, options);
74
+
75
+ if (tagObj[":@"]) {
76
+ assignAttributes(val, tagObj[":@"], matcher, options);
77
+ } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) {
78
+ val = val[options.textNodeName];
79
+ } else if (Object.keys(val).length === 0) {
80
+ if (options.alwaysCreateTextNode) val[options.textNodeName] = "";
81
+ else val = "";
82
+ }
83
+
84
+ if (tagObj[METADATA_SYMBOL] !== undefined && typeof val === "object" && val !== null) {
85
+ val[METADATA_SYMBOL] = tagObj[METADATA_SYMBOL]; // copy over metadata
86
+ }
87
+
88
+
89
+ if (compressedObj[property] !== undefined && Object.prototype.hasOwnProperty.call(compressedObj, property)) {
90
+ if (!Array.isArray(compressedObj[property])) {
91
+ compressedObj[property] = [compressedObj[property]];
92
+ }
93
+ compressedObj[property].push(val);
94
+ } else {
95
+ //TODO: if a node is not an array, then check if it should be an array
96
+ //also determine if it is a leaf node
97
+
98
+ // Pass jPath string or matcher based on options.jPath setting
99
+ const jPathOrMatcher = options.jPath ? matcher.toString() : matcher;
100
+ if (options.isArray(property, jPathOrMatcher, isLeaf)) {
101
+ compressedObj[property] = [val];
102
+ } else {
103
+ compressedObj[property] = val;
104
+ }
105
+ }
106
+
107
+ // Pop property from matcher after processing
108
+ if (property !== undefined && property !== options.textNodeName) {
109
+ matcher.pop();
110
+ }
111
+ }
112
+
113
+ }
114
+ // if(text && text.length > 0) compressedObj[options.textNodeName] = text;
115
+ if (typeof text === "string") {
116
+ if (text.length > 0) compressedObj[options.textNodeName] = text;
117
+ } else if (text !== undefined) compressedObj[options.textNodeName] = text;
118
+
119
+
120
+ return compressedObj;
121
+ }
122
+
123
+ function propName(obj) {
124
+ const keys = Object.keys(obj);
125
+ for (let i = 0; i < keys.length; i++) {
126
+ const key = keys[i];
127
+ if (key !== ":@") return key;
128
+ }
129
+ }
130
+
131
+ function assignAttributes(obj, attrMap, matcher, options) {
132
+ if (attrMap) {
133
+ const keys = Object.keys(attrMap);
134
+ const len = keys.length; //don't make it inline
135
+ for (let i = 0; i < len; i++) {
136
+ const atrrName = keys[i]; // This is the PREFIXED name (e.g., "@_class")
137
+
138
+ // Strip prefix for matcher path (for isArray callback)
139
+ const rawAttrName = atrrName.startsWith(options.attributeNamePrefix)
140
+ ? atrrName.substring(options.attributeNamePrefix.length)
141
+ : atrrName;
142
+
143
+ // For attributes, we need to create a temporary path
144
+ // Pass jPath string or matcher based on options.jPath setting
145
+ const jPathOrMatcher = options.jPath
146
+ ? matcher.toString() + "." + rawAttrName
147
+ : matcher;
148
+
149
+ if (options.isArray(atrrName, jPathOrMatcher, true, true)) {
150
+ obj[atrrName] = [attrMap[atrrName]];
151
+ } else {
152
+ obj[atrrName] = attrMap[atrrName];
153
+ }
154
+ }
155
+ }
156
+ }
157
+
158
+ function isLeafTag(obj, options) {
159
+ const { textNodeName } = options;
160
+ const propCount = Object.keys(obj).length;
161
+
162
+ if (propCount === 0) {
163
+ return true;
164
+ }
165
+
166
+ if (
167
+ propCount === 1 &&
168
+ (obj[textNodeName] || typeof obj[textNodeName] === "boolean" || obj[textNodeName] === 0)
169
+ ) {
170
+ return true;
171
+ }
172
+
173
+ return false;
174
+ }
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ let METADATA_SYMBOL;
4
+
5
+ if (typeof Symbol !== "function") {
6
+ METADATA_SYMBOL = "@@xmlMetadata";
7
+ } else {
8
+ METADATA_SYMBOL = Symbol("XML Node Metadata");
9
+ }
10
+
11
+ export default class XmlNode {
12
+ constructor(tagname) {
13
+ this.tagname = tagname;
14
+ this.child = []; //nested tags, text, cdata, comments in order
15
+ this[":@"] = Object.create(null); //attributes map
16
+ }
17
+ add(key, val) {
18
+ // this.child.push( {name : key, val: val, isCdata: isCdata });
19
+ if (key === "__proto__") key = "#__proto__";
20
+ this.child.push({ [key]: val });
21
+ }
22
+ addChild(node, startIndex) {
23
+ if (node.tagname === "__proto__") node.tagname = "#__proto__";
24
+ if (node[":@"] && Object.keys(node[":@"]).length > 0) {
25
+ this.child.push({ [node.tagname]: node.child, [":@"]: node[":@"] });
26
+ } else {
27
+ this.child.push({ [node.tagname]: node.child });
28
+ }
29
+ // if requested, add the startIndex
30
+ if (startIndex !== undefined) {
31
+ // Note: for now we just overwrite the metadata. If we had more complex metadata,
32
+ // we might need to do an object append here: metadata = { ...metadata, startIndex }
33
+ this.child[this.child.length - 1][METADATA_SYMBOL] = { startIndex };
34
+ }
35
+ }
36
+ /** symbol used for metadata */
37
+ static getMetaDataSymbol() {
38
+ return METADATA_SYMBOL;
39
+ }
40
+ }