@svta/cml-xml 1.0.2 → 1.1.1
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.
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -40
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ type XmlNode = {
|
|
|
11
11
|
childNodes: XmlNode[];
|
|
12
12
|
prefix?: string | null;
|
|
13
13
|
localName?: string;
|
|
14
|
+
parentElement?: XmlNode | null;
|
|
14
15
|
};
|
|
15
16
|
//#endregion
|
|
16
17
|
//#region src/getElementsByName.d.ts
|
|
@@ -37,6 +38,7 @@ type XmlParseOptions = {
|
|
|
37
38
|
pos?: number;
|
|
38
39
|
keepWhitespace?: boolean;
|
|
39
40
|
keepComments?: boolean;
|
|
41
|
+
includeParentElement?: boolean;
|
|
40
42
|
};
|
|
41
43
|
//#endregion
|
|
42
44
|
//#region src/parseXml.d.ts
|
|
@@ -50,7 +52,7 @@ type XmlParseOptions = {
|
|
|
50
52
|
* @public
|
|
51
53
|
*
|
|
52
54
|
* @example
|
|
53
|
-
* {@includeCode ../test/
|
|
55
|
+
* {@includeCode ../test/parseXml.test.ts#example}
|
|
54
56
|
*/
|
|
55
57
|
declare function parseXml(input: string, options?: XmlParseOptions): XmlNode;
|
|
56
58
|
//#endregion
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/XmlNode.ts","../src/getElementsByName.ts","../src/XmlParseOptions.ts","../src/parseXml.ts","../src/serializeXml.ts"],"sourcesContent":[],"mappings":";;AAMA;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/XmlNode.ts","../src/getElementsByName.ts","../src/XmlParseOptions.ts","../src/parseXml.ts","../src/serializeXml.ts"],"sourcesContent":[],"mappings":";;AAMA;;;;AAOiB,KAPL,OAAA,GAOK;;;cAJJ;ECIb,UAAgB,EDHH,OCGG,EAAA;EAAwB,MAAA,CAAA,EAAA,MAAA,GAAA,IAAA;EAA8B,SAAA,CAAA,EAAA,MAAA;EAAiB,aAAA,CAAA,EDAtE,OCAsE,GAAA,IAAA;CAAA;;;ADPvF;;;;;;;;ACOA;;;AAAuF,iBAAvE,iBAAA,CAAuE,IAAA,EAA/C,OAA+C,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAjB,OAAiB,EAAA,CAAA,EAAA,OAAA,EAAA;;;;ADPvF;;;;AAOiB,KERL,eAAA,GFQK;;;;ECAjB,oBAAgB,CAAA,EAAA,OAAA;CAAwB;;;;;;;;;;AAAxC;;;;;iBEkBgB,QAAA,0BAAiC,kBAAuB;;;AHzBxE;;;;;;;;ACOA;;;AAAuF,iBGAvE,YAAA,CHAuE,GAAA,EGArD,OHAqD,CAAA,EAAA,MAAA"}
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,25 @@ function getElementsByName(node, name, found = []) {
|
|
|
21
21
|
|
|
22
22
|
//#endregion
|
|
23
23
|
//#region src/parseXml.ts
|
|
24
|
+
const OPEN_BRACKET_CC = 60;
|
|
25
|
+
const CLOSE_BRACKET_CC = 62;
|
|
26
|
+
const MINUS_CC = 45;
|
|
27
|
+
const SLASH_CC = 47;
|
|
28
|
+
const QUESTION_CC = 63;
|
|
29
|
+
const EXCLAMATION_CC = 33;
|
|
30
|
+
const SINGLE_QUOTE_CC = 39;
|
|
31
|
+
const DOUBLE_QUOTE_CC = 34;
|
|
32
|
+
const OPEN_CORNER_BRACKET_CC = 91;
|
|
33
|
+
const CLOSE_CORNER_BRACKET_CC = 93;
|
|
34
|
+
const NAME_SPACER_SET = new Set([
|
|
35
|
+
13,
|
|
36
|
+
10,
|
|
37
|
+
9,
|
|
38
|
+
62,
|
|
39
|
+
47,
|
|
40
|
+
61,
|
|
41
|
+
32
|
|
42
|
+
]);
|
|
24
43
|
/**
|
|
25
44
|
* Parse XML into a JS object with no validation and some failure tolerance
|
|
26
45
|
*
|
|
@@ -31,26 +50,17 @@ function getElementsByName(node, name, found = []) {
|
|
|
31
50
|
* @public
|
|
32
51
|
*
|
|
33
52
|
* @example
|
|
34
|
-
* {@includeCode ../test/
|
|
53
|
+
* {@includeCode ../test/parseXml.test.ts#example}
|
|
35
54
|
*/
|
|
36
55
|
function parseXml(input, options = {}) {
|
|
37
56
|
let pos = options.pos || 0;
|
|
38
57
|
const length = input.length;
|
|
39
58
|
const keepComments = !!options.keepComments;
|
|
40
59
|
const keepWhitespace = !!options.keepWhitespace;
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const minusCC = "-".charCodeAt(0);
|
|
46
|
-
const slashCC = "/".charCodeAt(0);
|
|
47
|
-
const questionCC = "?".charCodeAt(0);
|
|
48
|
-
const exclamationCC = "!".charCodeAt(0);
|
|
49
|
-
const singleQuoteCC = "'".charCodeAt(0);
|
|
50
|
-
const doubleQuoteCC = "\"".charCodeAt(0);
|
|
51
|
-
const openCornerBracketCC = "[".charCodeAt(0);
|
|
52
|
-
const closeCornerBracketCC = "]".charCodeAt(0);
|
|
53
|
-
const nameSpacer = "\r\n >/= ";
|
|
60
|
+
const includeParentElement = !!options.includeParentElement;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a text node
|
|
63
|
+
*/
|
|
54
64
|
function createTextNode(value, nodeName = "#text") {
|
|
55
65
|
return {
|
|
56
66
|
nodeName,
|
|
@@ -60,33 +70,35 @@ function parseXml(input, options = {}) {
|
|
|
60
70
|
};
|
|
61
71
|
}
|
|
62
72
|
/**
|
|
63
|
-
*
|
|
73
|
+
* Parses a list of entries
|
|
64
74
|
*/
|
|
65
75
|
function parseChildren(tagName = "") {
|
|
66
76
|
const children = [];
|
|
67
|
-
while (
|
|
68
|
-
|
|
77
|
+
while (pos < length) if (input.charCodeAt(pos) === OPEN_BRACKET_CC) {
|
|
78
|
+
const next = input.charCodeAt(pos + 1);
|
|
79
|
+
if (next === SLASH_CC) {
|
|
69
80
|
const closeStart = pos + 2;
|
|
70
|
-
pos = input.indexOf(
|
|
81
|
+
pos = input.indexOf(">", pos);
|
|
71
82
|
if (!input.startsWith(tagName, closeStart)) {
|
|
72
83
|
const parsedText = input.substring(0, pos).split("\n");
|
|
73
84
|
throw new Error("Unexpected close tag\nLine: " + (parsedText.length - 1) + "\nColumn: " + (parsedText[parsedText.length - 1].length + 1) + "\nChar: " + input[pos]);
|
|
74
85
|
}
|
|
75
86
|
if (pos + 1) pos += 1;
|
|
76
87
|
return children;
|
|
77
|
-
} else if (
|
|
78
|
-
pos = input.indexOf(
|
|
88
|
+
} else if (next === QUESTION_CC) {
|
|
89
|
+
pos = input.indexOf(">", pos);
|
|
79
90
|
pos++;
|
|
80
91
|
continue;
|
|
81
|
-
} else if (
|
|
82
|
-
|
|
92
|
+
} else if (next === EXCLAMATION_CC) {
|
|
93
|
+
const third = input.charCodeAt(pos + 2);
|
|
94
|
+
if (third === MINUS_CC) {
|
|
83
95
|
const startCommentPos = pos;
|
|
84
|
-
while (pos !== -1 && !(input.charCodeAt(pos) ===
|
|
96
|
+
while (pos !== -1 && !(input.charCodeAt(pos) === CLOSE_BRACKET_CC && input.charCodeAt(pos - 1) === MINUS_CC && input.charCodeAt(pos - 2) === MINUS_CC)) pos = input.indexOf(">", pos + 1);
|
|
85
97
|
if (pos === -1) pos = length;
|
|
86
98
|
if (keepComments) children.push(createTextNode(input.substring(startCommentPos, pos + 1), "#comment"));
|
|
87
|
-
} else if (
|
|
99
|
+
} else if (third === OPEN_CORNER_BRACKET_CC && input.charCodeAt(pos + 8) === OPEN_CORNER_BRACKET_CC && input.startsWith("CDATA", pos + 3)) {
|
|
88
100
|
const cdataEndIndex = input.indexOf("]]>", pos);
|
|
89
|
-
if (cdataEndIndex
|
|
101
|
+
if (cdataEndIndex === -1) {
|
|
90
102
|
children.push(createTextNode(input.substr(pos + 9), "#cdata"));
|
|
91
103
|
pos = length;
|
|
92
104
|
} else {
|
|
@@ -98,9 +110,10 @@ function parseXml(input, options = {}) {
|
|
|
98
110
|
const startDoctype = pos + 1;
|
|
99
111
|
pos += 2;
|
|
100
112
|
let encapsuled = false;
|
|
101
|
-
while ((input.charCodeAt(pos) !==
|
|
102
|
-
|
|
103
|
-
|
|
113
|
+
while (pos < length && (input.charCodeAt(pos) !== CLOSE_BRACKET_CC || encapsuled)) {
|
|
114
|
+
const cc = input.charCodeAt(pos);
|
|
115
|
+
if (cc === OPEN_CORNER_BRACKET_CC) encapsuled = true;
|
|
116
|
+
else if (encapsuled && cc === CLOSE_CORNER_BRACKET_CC) encapsuled = false;
|
|
104
117
|
pos++;
|
|
105
118
|
}
|
|
106
119
|
children.push(createTextNode(input.substring(startDoctype, pos), "#doctype"));
|
|
@@ -123,38 +136,38 @@ function parseXml(input, options = {}) {
|
|
|
123
136
|
return children;
|
|
124
137
|
}
|
|
125
138
|
/**
|
|
126
|
-
*
|
|
139
|
+
* Returns the text outside of texts until the first '<'
|
|
127
140
|
*/
|
|
128
141
|
function parseText() {
|
|
129
142
|
const start = pos;
|
|
130
|
-
pos = input.indexOf(
|
|
143
|
+
pos = input.indexOf("<", pos) - 1;
|
|
131
144
|
if (pos === -2) pos = length;
|
|
132
145
|
return unescapeHtml(input.slice(start, pos + 1));
|
|
133
146
|
}
|
|
134
147
|
/**
|
|
135
|
-
*
|
|
148
|
+
* Returns text until the first nonAlphabetic letter
|
|
136
149
|
*/
|
|
137
150
|
function parseName() {
|
|
138
151
|
const start = pos;
|
|
139
|
-
while (
|
|
152
|
+
while (pos < length && !NAME_SPACER_SET.has(input.charCodeAt(pos))) pos++;
|
|
140
153
|
return input.slice(start, pos);
|
|
141
154
|
}
|
|
142
155
|
/**
|
|
143
|
-
*
|
|
156
|
+
* Parses the attributes of a node
|
|
144
157
|
*/
|
|
145
158
|
function parseAttributes() {
|
|
146
159
|
const attributes = {};
|
|
147
|
-
while (input.charCodeAt(pos) !==
|
|
160
|
+
while (pos < length && input.charCodeAt(pos) !== CLOSE_BRACKET_CC) {
|
|
148
161
|
const c = input.charCodeAt(pos);
|
|
149
162
|
if (c > 64 && c < 91 || c > 96 && c < 123) {
|
|
150
163
|
const name = parseName();
|
|
151
164
|
let value = "";
|
|
152
165
|
let code = input.charCodeAt(pos);
|
|
153
|
-
while (code !==
|
|
166
|
+
while (code !== SINGLE_QUOTE_CC && code !== DOUBLE_QUOTE_CC) {
|
|
154
167
|
pos++;
|
|
155
168
|
code = input.charCodeAt(pos);
|
|
156
169
|
}
|
|
157
|
-
if (code ===
|
|
170
|
+
if (code === SINGLE_QUOTE_CC || code === DOUBLE_QUOTE_CC) {
|
|
158
171
|
value = parseString();
|
|
159
172
|
if (pos === -1) throw new Error("Missing closing quote");
|
|
160
173
|
} else pos--;
|
|
@@ -165,7 +178,7 @@ function parseXml(input, options = {}) {
|
|
|
165
178
|
return attributes;
|
|
166
179
|
}
|
|
167
180
|
/**
|
|
168
|
-
*
|
|
181
|
+
* Parses a node
|
|
169
182
|
*/
|
|
170
183
|
function parseNode() {
|
|
171
184
|
pos++;
|
|
@@ -181,7 +194,7 @@ function parseXml(input, options = {}) {
|
|
|
181
194
|
let childNodes = [];
|
|
182
195
|
const prev = input.charCodeAt(pos - 1);
|
|
183
196
|
pos++;
|
|
184
|
-
if (prev !==
|
|
197
|
+
if (prev !== SLASH_CC) childNodes = parseChildren(nodeName);
|
|
185
198
|
return {
|
|
186
199
|
nodeName,
|
|
187
200
|
nodeValue: null,
|
|
@@ -192,7 +205,7 @@ function parseXml(input, options = {}) {
|
|
|
192
205
|
};
|
|
193
206
|
}
|
|
194
207
|
/**
|
|
195
|
-
*
|
|
208
|
+
* Parses a string, that starts with a char and with the same usually ' or "
|
|
196
209
|
*/
|
|
197
210
|
function parseString() {
|
|
198
211
|
const startChar = input[pos];
|
|
@@ -200,12 +213,21 @@ function parseXml(input, options = {}) {
|
|
|
200
213
|
pos = input.indexOf(startChar, startpos);
|
|
201
214
|
return input.slice(startpos, pos);
|
|
202
215
|
}
|
|
203
|
-
|
|
216
|
+
/**
|
|
217
|
+
* Recursively sets parentElement on all nodes in the tree
|
|
218
|
+
*/
|
|
219
|
+
function setParentElements(node, parent) {
|
|
220
|
+
node.parentElement = parent?.nodeName.startsWith("#") ? null : parent;
|
|
221
|
+
for (const child of node.childNodes) setParentElements(child, node);
|
|
222
|
+
}
|
|
223
|
+
const document = {
|
|
204
224
|
nodeName: "#document",
|
|
205
225
|
nodeValue: null,
|
|
206
226
|
childNodes: parseChildren(""),
|
|
207
227
|
attributes: {}
|
|
208
228
|
};
|
|
229
|
+
if (includeParentElement) setParentElements(document, null);
|
|
230
|
+
return document;
|
|
209
231
|
}
|
|
210
232
|
|
|
211
233
|
//#endregion
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["children: any[]","attributes: Record<string, string>","value: string","childNodes: any[]"],"sources":["../src/getElementsByName.ts","../src/parseXml.ts","../src/serializeXml.ts"],"sourcesContent":["import type { XmlNode } from './XmlNode.ts'\n\n/**\n * Recursively finds all elements by name within an XML structure.\n *\n * @param node - The current XML node to search within.\n * @param name - The name of the target nodes to find.\n * @param found - An array to collect matching nodes.\n * @returns An array of all matching XmlNodes.\n *\n * @public\n *\n */\nexport function getElementsByName(node: XmlNode, name: string, found: XmlNode[] = []): XmlNode[] {\n\tif (!node) {\n\t\treturn found\n\t}\n\n\tif (node.nodeName === name) {\n\t\tfound.push(node)\n\t}\n\n\tif (node.childNodes) {\n\t\tfor (const child of node.childNodes) {\n\t\t\tgetElementsByName(child, name, found)\n\t\t}\n\t}\n\n\treturn found\n}\n","import { unescapeHtml } from '@svta/cml-utils'\nimport type { XmlNode } from './XmlNode.ts'\nimport type { XmlParseOptions } from './XmlParseOptions.ts'\n\n/**\n * Parse XML into a JS object with no validation and some failure tolerance\n *\n * @param input - The input XML string\n * @param options - Optional parsing options\n * @returns The parsed XML\n *\n * @public\n *\n * @example\n * {@includeCode ../test/decodeXml.test.ts#example}\n */\nexport function parseXml(input: string, options: XmlParseOptions = {}): XmlNode {\n\tlet pos = options.pos || 0\n\n\tconst length = input.length\n\tconst keepComments = !!options.keepComments\n\tconst keepWhitespace = !!options.keepWhitespace\n\n\tconst openBracket = '<'\n\tconst openBracketCC = '<'.charCodeAt(0)\n\tconst closeBracket = '>'\n\tconst closeBracketCC = '>'.charCodeAt(0)\n\tconst minusCC = '-'.charCodeAt(0)\n\tconst slashCC = '/'.charCodeAt(0)\n\tconst questionCC = '?'.charCodeAt(0)\n\tconst exclamationCC = '!'.charCodeAt(0)\n\tconst singleQuoteCC = \"'\".charCodeAt(0)\n\tconst doubleQuoteCC = '\"'.charCodeAt(0)\n\tconst openCornerBracketCC = '['.charCodeAt(0)\n\tconst closeCornerBracketCC = ']'.charCodeAt(0)\n\tconst nameSpacer = '\\r\\n\\t>/= '\n\n\tfunction createTextNode(value: string, nodeName = '#text'): XmlNode {\n\t\treturn {\n\t\t\tnodeName,\n\t\t\tnodeValue: value,\n\t\t\tattributes: {},\n\t\t\tchildNodes: [],\n\t\t}\n\t}\n\n\t/**\n\t * parsing a list of entries\n\t */\n\tfunction parseChildren(tagName: string = ''): XmlNode[] {\n\t\tconst children: any[] = []\n\t\twhile (input[pos]) {\n\t\t\tif (input.charCodeAt(pos) == openBracketCC) {\n\t\t\t\tif (input.charCodeAt(pos + 1) === slashCC) {\n\t\t\t\t\tconst closeStart = pos + 2\n\t\t\t\t\tpos = input.indexOf(closeBracket, pos)\n\t\t\t\t\tif (!input.startsWith(tagName, closeStart)) {\n\t\t\t\t\t\tconst parsedText = input.substring(0, pos).split('\\n')\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Unexpected close tag\\nLine: ' + (parsedText.length - 1) +\n\t\t\t\t\t\t\t'\\nColumn: ' + (parsedText[parsedText.length - 1].length + 1) +\n\t\t\t\t\t\t\t'\\nChar: ' + input[pos],\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pos + 1) {\n\t\t\t\t\t\tpos += 1\n\t\t\t\t\t}\n\n\t\t\t\t\treturn children\n\t\t\t\t}\n\t\t\t\telse if (input.charCodeAt(pos + 1) === questionCC) {\n\t\t\t\t\t// xml declaration\n\t\t\t\t\tpos = input.indexOf(closeBracket, pos)\n\t\t\t\t\tpos++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\telse if (input.charCodeAt(pos + 1) === exclamationCC) {\n\t\t\t\t\tif (input.charCodeAt(pos + 2) == minusCC) {\n\t\t\t\t\t\t// comment support\n\t\t\t\t\t\tconst startCommentPos = pos\n\t\t\t\t\t\twhile (pos !== -1 && !(input.charCodeAt(pos) === closeBracketCC && input.charCodeAt(pos - 1) == minusCC && input.charCodeAt(pos - 2) == minusCC && pos != -1)) {\n\t\t\t\t\t\t\tpos = input.indexOf(closeBracket, pos + 1)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pos === -1) {\n\t\t\t\t\t\t\tpos = length\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (keepComments) {\n\t\t\t\t\t\t\tchildren.push(createTextNode(input.substring(startCommentPos, pos + 1), '#comment'))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (\n\t\t\t\t\t\tinput.charCodeAt(pos + 2) === openCornerBracketCC &&\n\t\t\t\t\t\tinput.charCodeAt(pos + 8) === openCornerBracketCC &&\n\t\t\t\t\t\tinput.startsWith('CDATA', pos + 3)\n\t\t\t\t\t) {\n\t\t\t\t\t\t// cdata\n\t\t\t\t\t\tconst cdataEndIndex = input.indexOf(']]>', pos)\n\t\t\t\t\t\tif (cdataEndIndex == -1) {\n\t\t\t\t\t\t\tchildren.push(createTextNode(input.substr(pos + 9), '#cdata'))\n\t\t\t\t\t\t\tpos = length\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tchildren.push(createTextNode(input.substring(pos + 9, cdataEndIndex), '#cdata'))\n\t\t\t\t\t\t\tpos = cdataEndIndex + 3\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// doctypesupport\n\t\t\t\t\t\tconst startDoctype = pos + 1\n\t\t\t\t\t\tpos += 2\n\t\t\t\t\t\tlet encapsuled = false\n\t\t\t\t\t\twhile ((input.charCodeAt(pos) !== closeBracketCC || encapsuled === true) && input[pos]) {\n\t\t\t\t\t\t\tif (input.charCodeAt(pos) === openCornerBracketCC) {\n\t\t\t\t\t\t\t\tencapsuled = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (encapsuled === true && input.charCodeAt(pos) === closeCornerBracketCC) {\n\t\t\t\t\t\t\t\tencapsuled = false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpos++\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchildren.push(createTextNode(input.substring(startDoctype, pos), '#doctype'))\n\t\t\t\t\t}\n\n\t\t\t\t\tpos++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tconst node = parseNode()\n\t\t\t\tchildren.push(node)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst text = parseText()\n\t\t\t\tif (keepWhitespace) {\n\t\t\t\t\tif (text.length > 0) {\n\t\t\t\t\t\tchildren.push(createTextNode(text))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconst trimmed = text.trim()\n\t\t\t\t\tif (trimmed.length > 0) {\n\t\t\t\t\t\tchildren.push(createTextNode(trimmed))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpos++\n\t\t\t}\n\t\t}\n\t\treturn children\n\t}\n\n\t/**\n\t * returns the text outside of texts until the first '<'\n\t */\n\tfunction parseText(): string {\n\t\tconst start = pos\n\t\tpos = input.indexOf(openBracket, pos) - 1\n\t\tif (pos === -2) {\n\t\t\tpos = length\n\t\t}\n\n\t\treturn unescapeHtml(input.slice(start, pos + 1))\n\t}\n\n\t/**\n\t * returns text until the first nonAlphabetic letter\n\t */\n\tfunction parseName(): string {\n\t\tconst start = pos\n\t\twhile (nameSpacer.indexOf(input[pos]) === -1 && input[pos]) {\n\t\t\tpos++\n\t\t}\n\t\treturn input.slice(start, pos)\n\t}\n\n\t/**\n\t * parses the attributes of a node\n\t */\n\tfunction parseAttributes(): Record<string, string> {\n\t\tconst attributes: Record<string, string> = {}\n\n\t\t// parsing attributes\n\t\twhile (input.charCodeAt(pos) !== closeBracketCC && input[pos]) {\n\t\t\tconst c = input.charCodeAt(pos)\n\t\t\tif ((c > 64 && c < 91) || (c > 96 && c < 123)) {\n\t\t\t\tconst name = parseName()\n\t\t\t\tlet value: string = ''\n\t\t\t\t// search beginning of the string\n\t\t\t\tlet code = input.charCodeAt(pos)\n\t\t\t\twhile (code !== singleQuoteCC && code !== doubleQuoteCC) {\n\t\t\t\t\tpos++\n\t\t\t\t\tcode = input.charCodeAt(pos)\n\t\t\t\t}\n\n\t\t\t\tif (code === singleQuoteCC || code === doubleQuoteCC) {\n\t\t\t\t\tvalue = parseString()\n\t\t\t\t\tif (pos === -1) {\n\t\t\t\t\t\tthrow new Error('Missing closing quote')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpos--\n\t\t\t\t}\n\n\t\t\t\tattributes[name] = unescapeHtml(value)\n\t\t\t}\n\t\t\tpos++\n\t\t}\n\n\t\treturn attributes\n\t}\n\n\t/**\n\t * parses a node\n\t */\n\tfunction parseNode(): XmlNode {\n\t\tpos++\n\t\tconst nodeName = parseName()\n\t\tlet localName = nodeName\n\t\tlet prefix = null\n\n\t\tconst nsIndex = nodeName.indexOf(':')\n\t\tif (nsIndex !== -1) {\n\t\t\tprefix = nodeName.slice(0, nsIndex)\n\t\t\tlocalName = nodeName.slice(nsIndex + 1)\n\t\t}\n\n\t\tconst attributes = parseAttributes()\n\n\t\tlet childNodes: any[] = []\n\n\t\t// optional parsing of children\n\t\tconst prev = input.charCodeAt(pos - 1)\n\t\tpos++\n\n\t\tif (prev !== slashCC) {\n\t\t\tchildNodes = parseChildren(nodeName)\n\t\t}\n\n\t\treturn {\n\t\t\tnodeName,\n\t\t\tnodeValue: null,\n\t\t\tattributes,\n\t\t\tchildNodes,\n\t\t\tprefix,\n\t\t\tlocalName,\n\t\t}\n\t}\n\n\t/**\n\t * is parsing a string, that starts with a char and with the same usually ' or \"\n\t */\n\tfunction parseString(): string {\n\t\tconst startChar = input[pos]\n\t\tconst startpos = pos + 1\n\t\tpos = input.indexOf(startChar, startpos)\n\t\treturn input.slice(startpos, pos)\n\t}\n\n\treturn {\n\t\tnodeName: '#document',\n\t\tnodeValue: null,\n\t\tchildNodes: parseChildren(''),\n\t\tattributes: {},\n\t}\n}\n","import type { XmlNode } from './XmlNode.ts'\n\n/**\n * Basic xml encoding utility. Encodes XML into a string.\n *\n * @param xml - The XML node to encode\n * @returns The parsed XML\n *\n * @public\n *\n * @example\n * {@includeCode ../test/serializeXml.test.ts#example}\n */\nexport function serializeXml(xml: XmlNode): string {\n\tconst { nodeName, attributes, childNodes } = xml\n\n\tif (nodeName === '#document') {\n\t\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>${serializeXml(childNodes[0])}`\n\t}\n\n\tif (nodeName === '#text') {\n\t\treturn xml.nodeValue || ''\n\t}\n\n\tlet result = `<${nodeName}`\n\n\tif (attributes) {\n\t\tfor (const key in attributes) {\n\t\t\tresult += ` ${key}=${JSON.stringify(attributes[key])}`\n\t\t}\n\t}\n\n\tlet children = ''\n\n\tconst childCount = childNodes?.length\n\n\tif (childCount) {\n\t\tfor (let i = 0; i < childCount; i++) {\n\t\t\tchildren += serializeXml(childNodes[i])\n\t\t}\n\t}\n\n\tconst close = (!children) ? ' />' : `>${children}</${nodeName}>`\n\tresult += close\n\n\treturn result\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["children: XmlNode[]","attributes: Record<string, string>","value: string","childNodes: any[]","document: XmlNode"],"sources":["../src/getElementsByName.ts","../src/parseXml.ts","../src/serializeXml.ts"],"sourcesContent":["import type { XmlNode } from './XmlNode.ts'\n\n/**\n * Recursively finds all elements by name within an XML structure.\n *\n * @param node - The current XML node to search within.\n * @param name - The name of the target nodes to find.\n * @param found - An array to collect matching nodes.\n * @returns An array of all matching XmlNodes.\n *\n * @public\n *\n */\nexport function getElementsByName(node: XmlNode, name: string, found: XmlNode[] = []): XmlNode[] {\n\tif (!node) {\n\t\treturn found\n\t}\n\n\tif (node.nodeName === name) {\n\t\tfound.push(node)\n\t}\n\n\tif (node.childNodes) {\n\t\tfor (const child of node.childNodes) {\n\t\t\tgetElementsByName(child, name, found)\n\t\t}\n\t}\n\n\treturn found\n}\n","import { unescapeHtml } from '@svta/cml-utils'\nimport type { XmlNode } from './XmlNode.ts'\nimport type { XmlParseOptions } from './XmlParseOptions.ts'\n\n// Character code constants (computed once at module load)\nconst OPEN_BRACKET_CC = 60 // '<'\nconst CLOSE_BRACKET_CC = 62 // '>'\nconst MINUS_CC = 45 // '-'\nconst SLASH_CC = 47 // '/'\nconst QUESTION_CC = 63 // '?'\nconst EXCLAMATION_CC = 33 // '!'\nconst SINGLE_QUOTE_CC = 39 // \"'\"\nconst DOUBLE_QUOTE_CC = 34 // '\"'\nconst OPEN_CORNER_BRACKET_CC = 91 // '['\nconst CLOSE_CORNER_BRACKET_CC = 93 // ']'\n\n// Set for fast name delimiter lookup: \\r \\n \\t > / = space\nconst NAME_SPACER_SET = new Set([13, 10, 9, 62, 47, 61, 32])\n\n/**\n * Parse XML into a JS object with no validation and some failure tolerance\n *\n * @param input - The input XML string\n * @param options - Optional parsing options\n * @returns The parsed XML\n *\n * @public\n *\n * @example\n * {@includeCode ../test/parseXml.test.ts#example}\n */\nexport function parseXml(input: string, options: XmlParseOptions = {}): XmlNode {\n\tlet pos = options.pos || 0\n\n\tconst length = input.length\n\tconst keepComments = !!options.keepComments\n\tconst keepWhitespace = !!options.keepWhitespace\n\tconst includeParentElement = !!options.includeParentElement\n\n\t/**\n\t * Creates a text node\n\t */\n\tfunction createTextNode(value: string, nodeName = '#text'): XmlNode {\n\t\treturn {\n\t\t\tnodeName,\n\t\t\tnodeValue: value,\n\t\t\tattributes: {},\n\t\t\tchildNodes: [],\n\t\t}\n\t}\n\n\t/**\n\t * Parses a list of entries\n\t */\n\tfunction parseChildren(tagName: string = ''): XmlNode[] {\n\t\tconst children: XmlNode[] = []\n\t\twhile (pos < length) {\n\t\t\tconst c = input.charCodeAt(pos)\n\t\t\tif (c === OPEN_BRACKET_CC) {\n\t\t\t\tconst next = input.charCodeAt(pos + 1)\n\t\t\t\tif (next === SLASH_CC) {\n\t\t\t\t\tconst closeStart = pos + 2\n\t\t\t\t\tpos = input.indexOf('>', pos)\n\t\t\t\t\tif (!input.startsWith(tagName, closeStart)) {\n\t\t\t\t\t\tconst parsedText = input.substring(0, pos).split('\\n')\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t'Unexpected close tag\\nLine: ' + (parsedText.length - 1) +\n\t\t\t\t\t\t\t'\\nColumn: ' + (parsedText[parsedText.length - 1].length + 1) +\n\t\t\t\t\t\t\t'\\nChar: ' + input[pos],\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (pos + 1) {\n\t\t\t\t\t\tpos += 1\n\t\t\t\t\t}\n\n\t\t\t\t\treturn children\n\t\t\t\t}\n\t\t\t\telse if (next === QUESTION_CC) {\n\t\t\t\t\t// xml declaration\n\t\t\t\t\tpos = input.indexOf('>', pos)\n\t\t\t\t\tpos++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\telse if (next === EXCLAMATION_CC) {\n\t\t\t\t\tconst third = input.charCodeAt(pos + 2)\n\t\t\t\t\tif (third === MINUS_CC) {\n\t\t\t\t\t\t// comment support\n\t\t\t\t\t\tconst startCommentPos = pos\n\t\t\t\t\t\twhile (pos !== -1 && !(input.charCodeAt(pos) === CLOSE_BRACKET_CC && input.charCodeAt(pos - 1) === MINUS_CC && input.charCodeAt(pos - 2) === MINUS_CC)) {\n\t\t\t\t\t\t\tpos = input.indexOf('>', pos + 1)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (pos === -1) {\n\t\t\t\t\t\t\tpos = length\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (keepComments) {\n\t\t\t\t\t\t\tchildren.push(createTextNode(input.substring(startCommentPos, pos + 1), '#comment'))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse if (\n\t\t\t\t\t\tthird === OPEN_CORNER_BRACKET_CC &&\n\t\t\t\t\t\tinput.charCodeAt(pos + 8) === OPEN_CORNER_BRACKET_CC &&\n\t\t\t\t\t\tinput.startsWith('CDATA', pos + 3)\n\t\t\t\t\t) {\n\t\t\t\t\t\t// cdata\n\t\t\t\t\t\tconst cdataEndIndex = input.indexOf(']]>', pos)\n\t\t\t\t\t\tif (cdataEndIndex === -1) {\n\t\t\t\t\t\t\tchildren.push(createTextNode(input.substr(pos + 9), '#cdata'))\n\t\t\t\t\t\t\tpos = length\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tchildren.push(createTextNode(input.substring(pos + 9, cdataEndIndex), '#cdata'))\n\t\t\t\t\t\t\tpos = cdataEndIndex + 3\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\t// doctypesupport\n\t\t\t\t\t\tconst startDoctype = pos + 1\n\t\t\t\t\t\tpos += 2\n\t\t\t\t\t\tlet encapsuled = false\n\t\t\t\t\t\twhile (pos < length && (input.charCodeAt(pos) !== CLOSE_BRACKET_CC || encapsuled)) {\n\t\t\t\t\t\t\tconst cc = input.charCodeAt(pos)\n\t\t\t\t\t\t\tif (cc === OPEN_CORNER_BRACKET_CC) {\n\t\t\t\t\t\t\t\tencapsuled = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse if (encapsuled && cc === CLOSE_CORNER_BRACKET_CC) {\n\t\t\t\t\t\t\t\tencapsuled = false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tpos++\n\t\t\t\t\t\t}\n\t\t\t\t\t\tchildren.push(createTextNode(input.substring(startDoctype, pos), '#doctype'))\n\t\t\t\t\t}\n\n\t\t\t\t\tpos++\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tconst node = parseNode()\n\t\t\t\tchildren.push(node)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconst text = parseText()\n\t\t\t\tif (keepWhitespace) {\n\t\t\t\t\tif (text.length > 0) {\n\t\t\t\t\t\tchildren.push(createTextNode(text))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconst trimmed = text.trim()\n\t\t\t\t\tif (trimmed.length > 0) {\n\t\t\t\t\t\tchildren.push(createTextNode(trimmed))\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tpos++\n\t\t\t}\n\t\t}\n\t\treturn children\n\t}\n\n\t/**\n\t * Returns the text outside of texts until the first '<'\n\t */\n\tfunction parseText(): string {\n\t\tconst start = pos\n\t\tpos = input.indexOf('<', pos) - 1\n\t\tif (pos === -2) {\n\t\t\tpos = length\n\t\t}\n\n\t\treturn unescapeHtml(input.slice(start, pos + 1))\n\t}\n\n\t/**\n\t * Returns text until the first nonAlphabetic letter\n\t */\n\tfunction parseName(): string {\n\t\tconst start = pos\n\t\twhile (pos < length && !NAME_SPACER_SET.has(input.charCodeAt(pos))) {\n\t\t\tpos++\n\t\t}\n\t\treturn input.slice(start, pos)\n\t}\n\n\t/**\n\t * Parses the attributes of a node\n\t */\n\tfunction parseAttributes(): Record<string, string> {\n\t\tconst attributes: Record<string, string> = {}\n\n\t\t// parsing attributes\n\t\twhile (pos < length && input.charCodeAt(pos) !== CLOSE_BRACKET_CC) {\n\t\t\tconst c = input.charCodeAt(pos)\n\t\t\tif ((c > 64 && c < 91) || (c > 96 && c < 123)) {\n\t\t\t\tconst name = parseName()\n\t\t\t\tlet value: string = ''\n\t\t\t\t// search beginning of the string\n\t\t\t\tlet code = input.charCodeAt(pos)\n\t\t\t\twhile (code !== SINGLE_QUOTE_CC && code !== DOUBLE_QUOTE_CC) {\n\t\t\t\t\tpos++\n\t\t\t\t\tcode = input.charCodeAt(pos)\n\t\t\t\t}\n\n\t\t\t\tif (code === SINGLE_QUOTE_CC || code === DOUBLE_QUOTE_CC) {\n\t\t\t\t\tvalue = parseString()\n\t\t\t\t\tif (pos === -1) {\n\t\t\t\t\t\tthrow new Error('Missing closing quote')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tpos--\n\t\t\t\t}\n\n\t\t\t\tattributes[name] = unescapeHtml(value)\n\t\t\t}\n\t\t\tpos++\n\t\t}\n\n\t\treturn attributes\n\t}\n\n\t/**\n\t * Parses a node\n\t */\n\tfunction parseNode(): XmlNode {\n\t\tpos++\n\t\tconst nodeName = parseName()\n\t\tlet localName = nodeName\n\t\tlet prefix = null\n\n\t\tconst nsIndex = nodeName.indexOf(':')\n\t\tif (nsIndex !== -1) {\n\t\t\tprefix = nodeName.slice(0, nsIndex)\n\t\t\tlocalName = nodeName.slice(nsIndex + 1)\n\t\t}\n\n\t\tconst attributes = parseAttributes()\n\n\t\tlet childNodes: any[] = []\n\n\t\t// optional parsing of children\n\t\tconst prev = input.charCodeAt(pos - 1)\n\t\tpos++\n\n\t\tif (prev !== SLASH_CC) {\n\t\t\tchildNodes = parseChildren(nodeName)\n\t\t}\n\n\t\treturn {\n\t\t\tnodeName,\n\t\t\tnodeValue: null,\n\t\t\tattributes,\n\t\t\tchildNodes,\n\t\t\tprefix,\n\t\t\tlocalName,\n\t\t}\n\t}\n\n\t/**\n\t * Parses a string, that starts with a char and with the same usually ' or \"\n\t */\n\tfunction parseString(): string {\n\t\tconst startChar = input[pos]\n\t\tconst startpos = pos + 1\n\t\tpos = input.indexOf(startChar, startpos)\n\t\treturn input.slice(startpos, pos)\n\t}\n\n\t/**\n\t * Recursively sets parentElement on all nodes in the tree\n\t */\n\tfunction setParentElements(node: XmlNode, parent: XmlNode | null): void {\n\t\tnode.parentElement = parent?.nodeName.startsWith('#') ? null : parent\n\t\tfor (const child of node.childNodes) {\n\t\t\tsetParentElements(child, node)\n\t\t}\n\t}\n\n\tconst document: XmlNode = {\n\t\tnodeName: '#document',\n\t\tnodeValue: null,\n\t\tchildNodes: parseChildren(''),\n\t\tattributes: {},\n\t}\n\n\tif (includeParentElement) {\n\t\tsetParentElements(document, null)\n\t}\n\n\treturn document\n}\n","import type { XmlNode } from './XmlNode.ts'\n\n/**\n * Basic xml encoding utility. Encodes XML into a string.\n *\n * @param xml - The XML node to encode\n * @returns The parsed XML\n *\n * @public\n *\n * @example\n * {@includeCode ../test/serializeXml.test.ts#example}\n */\nexport function serializeXml(xml: XmlNode): string {\n\tconst { nodeName, attributes, childNodes } = xml\n\n\tif (nodeName === '#document') {\n\t\treturn `<?xml version=\"1.0\" encoding=\"UTF-8\"?>${serializeXml(childNodes[0])}`\n\t}\n\n\tif (nodeName === '#text') {\n\t\treturn xml.nodeValue || ''\n\t}\n\n\tlet result = `<${nodeName}`\n\n\tif (attributes) {\n\t\tfor (const key in attributes) {\n\t\t\tresult += ` ${key}=${JSON.stringify(attributes[key])}`\n\t\t}\n\t}\n\n\tlet children = ''\n\n\tconst childCount = childNodes?.length\n\n\tif (childCount) {\n\t\tfor (let i = 0; i < childCount; i++) {\n\t\t\tchildren += serializeXml(childNodes[i])\n\t\t}\n\t}\n\n\tconst close = (!children) ? ' />' : `>${children}</${nodeName}>`\n\tresult += close\n\n\treturn result\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svta/cml-xml",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "XML parsing utilities",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -50,6 +50,6 @@
|
|
|
50
50
|
}
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@svta/cml-utils": "1.
|
|
53
|
+
"@svta/cml-utils": "1.2.0"
|
|
54
54
|
}
|
|
55
55
|
}
|