xml-tokenizer 0.0.22 → 0.0.24
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/cjs/get-q-name.js +7 -1
- package/dist/cjs/index.js +75 -1
- package/dist/cjs/selector/TokenSelectState.js +106 -1
- package/dist/cjs/selector/TokenSelectStateMachine.js +150 -1
- package/dist/cjs/selector/TokenSelector.js +139 -1
- package/dist/cjs/selector/match-string.js +21 -1
- package/dist/cjs/selector/select.js +19 -1
- package/dist/cjs/token-to-xml.js +44 -1
- package/dist/cjs/tokenizer/XmlError.js +96 -1
- package/dist/cjs/tokenizer/XmlStream.js +447 -1
- package/dist/cjs/tokenizer/ascii-constants.js +69 -1
- package/dist/cjs/tokenizer/tokenize.js +408 -1
- package/dist/cjs/tokenizer/utils.js +47 -1
- package/dist/cjs/tokens-to-xml.js +13 -1
- package/dist/cjs/xml-to-object.js +69 -1
- package/dist/cjs/xml-to-simplified-object.js +86 -1
- package/dist/esm/get-q-name.js +5 -1
- package/dist/esm/index.js +14 -1
- package/dist/esm/selector/TokenSelectState.js +102 -1
- package/dist/esm/selector/TokenSelectStateMachine.js +148 -1
- package/dist/esm/selector/TokenSelector.js +137 -1
- package/dist/esm/selector/match-string.js +19 -1
- package/dist/esm/selector/select.js +17 -1
- package/dist/esm/token-to-xml.js +42 -1
- package/dist/esm/tokenizer/XmlError.js +94 -1
- package/dist/esm/tokenizer/XmlStream.js +445 -1
- package/dist/esm/tokenizer/ascii-constants.js +35 -1
- package/dist/esm/tokenizer/tokenize.js +405 -1
- package/dist/esm/tokenizer/utils.js +40 -1
- package/dist/esm/tokens-to-xml.js +11 -1
- package/dist/esm/xml-to-object.js +66 -1
- package/dist/esm/xml-to-simplified-object.js +83 -1
- package/dist/types/get-q-name.d.ts +1 -0
- package/dist/types/get-q-name.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/selector/TokenSelectState.d.ts +1 -0
- package/dist/types/selector/TokenSelectState.d.ts.map +1 -0
- package/dist/types/selector/TokenSelectStateMachine.d.ts +1 -0
- package/dist/types/selector/TokenSelectStateMachine.d.ts.map +1 -0
- package/dist/types/selector/TokenSelector.d.ts +1 -0
- package/dist/types/selector/TokenSelector.d.ts.map +1 -0
- package/dist/types/selector/index.d.ts +1 -0
- package/dist/types/selector/index.d.ts.map +1 -0
- package/dist/types/selector/match-string.d.ts +1 -0
- package/dist/types/selector/match-string.d.ts.map +1 -0
- package/dist/types/selector/select.d.ts +1 -0
- package/dist/types/selector/select.d.ts.map +1 -0
- package/dist/types/selector/types.d.ts +1 -0
- package/dist/types/selector/types.d.ts.map +1 -0
- package/dist/types/token-to-xml.d.ts +1 -0
- package/dist/types/token-to-xml.d.ts.map +1 -0
- package/dist/types/tokenizer/XmlError.d.ts +1 -0
- package/dist/types/tokenizer/XmlError.d.ts.map +1 -0
- package/dist/types/tokenizer/XmlStream.d.ts +3 -7
- package/dist/types/tokenizer/XmlStream.d.ts.map +1 -0
- package/dist/types/tokenizer/ascii-constants.d.ts +1 -0
- package/dist/types/tokenizer/ascii-constants.d.ts.map +1 -0
- package/dist/types/tokenizer/index.d.ts +1 -0
- package/dist/types/tokenizer/index.d.ts.map +1 -0
- package/dist/types/tokenizer/tokenize.d.ts +1 -0
- package/dist/types/tokenizer/tokenize.d.ts.map +1 -0
- package/dist/types/tokenizer/types.d.ts +1 -0
- package/dist/types/tokenizer/types.d.ts.map +1 -0
- package/dist/types/tokenizer/utils.d.ts +1 -0
- package/dist/types/tokenizer/utils.d.ts.map +1 -0
- package/dist/types/tokens-to-xml.d.ts +1 -0
- package/dist/types/tokens-to-xml.d.ts.map +1 -0
- package/dist/types/xml-to-object.d.ts +1 -0
- package/dist/types/xml-to-object.d.ts.map +1 -0
- package/dist/types/xml-to-simplified-object.d.ts +1 -0
- package/dist/types/xml-to-simplified-object.d.ts.map +1 -0
- package/package.json +4 -4
|
@@ -1 +1,408 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var getQName = require('../get-q-name.js');
|
|
4
|
+
var asciiConstants = require('./ascii-constants.js');
|
|
5
|
+
var utils = require('./utils.js');
|
|
6
|
+
var XmlError = require('./XmlError.js');
|
|
7
|
+
var XmlStream = require('./XmlStream.js');
|
|
8
|
+
|
|
9
|
+
const BOM = "\uFEFF";
|
|
10
|
+
const XML_DECLARATION_START = "<?xml ";
|
|
11
|
+
const XML_DECLARATION_END = "?>";
|
|
12
|
+
const ENTITY_DECLARATION_START = "<!ENTITY";
|
|
13
|
+
const ELEMENT_DECLARATION_START = "<!ELEMENT";
|
|
14
|
+
const ATTLIST_DECLARATION_START = "<!ATTLIST";
|
|
15
|
+
const NOTATION_DECLARATION_START = "<!NOTATION";
|
|
16
|
+
const DOCTYPE_START = "<!DOCTYPE";
|
|
17
|
+
const PI_START = "<?";
|
|
18
|
+
const PI_END = "?>";
|
|
19
|
+
const COMMENT_START = "<!--";
|
|
20
|
+
const COMMENT_END = "-->";
|
|
21
|
+
const CDATA_START = "<![CDATA[";
|
|
22
|
+
const CDATA_END = "]]>";
|
|
23
|
+
const NDATA = "NDATA";
|
|
24
|
+
const PUBLIC = "PUBLIC";
|
|
25
|
+
const SYSTEM = "SYSTEM";
|
|
26
|
+
const VERSION = "version";
|
|
27
|
+
const ENCODING = "encoding";
|
|
28
|
+
const STANDALONE = "standalone";
|
|
29
|
+
function tokenize(xmlString, tokenCallback, options = {}) {
|
|
30
|
+
tokenizeXmlStream(new XmlStream.XmlStream(xmlString, options), tokenCallback);
|
|
31
|
+
}
|
|
32
|
+
function tokenizeXmlStream(s, tokenCallback) {
|
|
33
|
+
if (s.startsWith(BOM)) {
|
|
34
|
+
s.advance(1);
|
|
35
|
+
}
|
|
36
|
+
if (s.startsWith(XML_DECLARATION_START)) {
|
|
37
|
+
parseDeclaration(s);
|
|
38
|
+
}
|
|
39
|
+
parseMisc(s, tokenCallback);
|
|
40
|
+
s.skipSpaces();
|
|
41
|
+
if (s.startsWith(DOCTYPE_START) || s.startsWith(DOCTYPE_START.toLowerCase())) {
|
|
42
|
+
if (!s.config.allowDtd) {
|
|
43
|
+
throw new XmlError.XmlError({ type: "DtdDetected" });
|
|
44
|
+
}
|
|
45
|
+
parseDoctype(s, tokenCallback);
|
|
46
|
+
parseMisc(s, tokenCallback);
|
|
47
|
+
}
|
|
48
|
+
s.skipSpaces();
|
|
49
|
+
if (s.config.strictDocument) {
|
|
50
|
+
if (!s.atEnd() && s.currCodeUnit() === asciiConstants.LESS_THAN) {
|
|
51
|
+
parseElement(s, tokenCallback);
|
|
52
|
+
}
|
|
53
|
+
parseMisc(s, tokenCallback);
|
|
54
|
+
if (!s.atEnd()) {
|
|
55
|
+
throw new XmlError.XmlError({ type: "UnknownToken", message: "Not at end" }, s.genTextPos());
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
while (!s.atEnd()) {
|
|
59
|
+
if (s.currCodeUnit() === asciiConstants.LESS_THAN) {
|
|
60
|
+
parseElement(s, tokenCallback);
|
|
61
|
+
} else {
|
|
62
|
+
parseText(s, tokenCallback);
|
|
63
|
+
}
|
|
64
|
+
parseMisc(s, tokenCallback);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function parseMisc(s, tokenCallback) {
|
|
69
|
+
while (!s.atEnd()) {
|
|
70
|
+
s.skipSpaces();
|
|
71
|
+
if (s.startsWith(COMMENT_START)) {
|
|
72
|
+
parseComment(s, tokenCallback);
|
|
73
|
+
} else if (s.startsWith(PI_START)) {
|
|
74
|
+
parsePi(s, tokenCallback);
|
|
75
|
+
} else {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function parseDeclaration(s) {
|
|
81
|
+
function consumeSpaces(_s) {
|
|
82
|
+
if (_s.startsWithSpace()) {
|
|
83
|
+
_s.skipSpaces();
|
|
84
|
+
} else if (!_s.startsWith(XML_DECLARATION_END) && !_s.atEnd()) {
|
|
85
|
+
throw new XmlError.XmlError(
|
|
86
|
+
{ type: "InvalidChar", expected: "a whitespace", actual: _s.currCodeUnitUnchecked() },
|
|
87
|
+
_s.genTextPos()
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
s.advance(5);
|
|
92
|
+
consumeSpaces(s);
|
|
93
|
+
if (!s.startsWith(VERSION)) {
|
|
94
|
+
throw new XmlError.XmlError({ type: "InvalidString", expected: "version" }, s.genTextPos());
|
|
95
|
+
}
|
|
96
|
+
parseAttribute(s);
|
|
97
|
+
consumeSpaces(s);
|
|
98
|
+
if (s.startsWith(ENCODING)) {
|
|
99
|
+
parseAttribute(s);
|
|
100
|
+
consumeSpaces(s);
|
|
101
|
+
}
|
|
102
|
+
if (s.startsWith(STANDALONE)) {
|
|
103
|
+
parseAttribute(s);
|
|
104
|
+
}
|
|
105
|
+
s.skipSpaces();
|
|
106
|
+
s.skipString(XML_DECLARATION_END);
|
|
107
|
+
}
|
|
108
|
+
function parseComment(s, tokenCallback) {
|
|
109
|
+
const start = s.getPos();
|
|
110
|
+
s.advance(4);
|
|
111
|
+
const text = s.consumeCodeUnitsWhile((c, _s) => !(c === asciiConstants.HYPHEN && _s.startsWith(COMMENT_END)));
|
|
112
|
+
s.skipString(COMMENT_END);
|
|
113
|
+
if (text.includes("--") || text.endsWith("-")) {
|
|
114
|
+
throw new XmlError.XmlError({ type: "InvalidComment" }, s.genTextPosFrom(start));
|
|
115
|
+
}
|
|
116
|
+
tokenCallback({ type: "Comment", text, range: s.rangeFrom(start) });
|
|
117
|
+
}
|
|
118
|
+
function parsePi(s, tokenCallback) {
|
|
119
|
+
if (s.startsWith(XML_DECLARATION_START)) {
|
|
120
|
+
throw new XmlError.XmlError({ type: "UnexpectedDeclaration" }, s.genTextPos());
|
|
121
|
+
}
|
|
122
|
+
const start = s.getPos();
|
|
123
|
+
s.advance(2);
|
|
124
|
+
const target = s.consumeName();
|
|
125
|
+
s.skipSpaces();
|
|
126
|
+
const content = s.consumeCodeUnitsWhile(
|
|
127
|
+
(c, _s) => !(c === asciiConstants.QUESTION_MARK && _s.startsWith(PI_END))
|
|
128
|
+
);
|
|
129
|
+
s.skipString(PI_END);
|
|
130
|
+
tokenCallback({
|
|
131
|
+
type: "ProcessingInstruction",
|
|
132
|
+
target,
|
|
133
|
+
content: content.length === 0 ? void 0 : content,
|
|
134
|
+
range: s.rangeFrom(start)
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function parseDoctype(s, tokenCallback) {
|
|
138
|
+
const start = s.getPos();
|
|
139
|
+
parseDoctypeStart(s);
|
|
140
|
+
s.skipSpaces();
|
|
141
|
+
if (s.currCodeUnit() === asciiConstants.GREATER_THAN) {
|
|
142
|
+
s.advance(1);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
s.advance(1);
|
|
146
|
+
while (!s.atEnd()) {
|
|
147
|
+
s.skipSpaces();
|
|
148
|
+
if (s.startsWith(ENTITY_DECLARATION_START)) {
|
|
149
|
+
parseEntityDecl(s, tokenCallback);
|
|
150
|
+
} else if (s.startsWith(COMMENT_START)) {
|
|
151
|
+
parseComment(s, tokenCallback);
|
|
152
|
+
} else if (s.startsWith(PI_START)) {
|
|
153
|
+
parsePi(s, tokenCallback);
|
|
154
|
+
} else if (s.startsWith("]")) {
|
|
155
|
+
s.advance(1);
|
|
156
|
+
s.skipSpaces();
|
|
157
|
+
if (s.currCodeUnit() === asciiConstants.GREATER_THAN) {
|
|
158
|
+
s.advance(1);
|
|
159
|
+
break;
|
|
160
|
+
} else {
|
|
161
|
+
throw new XmlError.XmlError(
|
|
162
|
+
{ type: "InvalidChar", expected: "'>'", actual: s.currCodeUnitUnchecked() },
|
|
163
|
+
s.genTextPos()
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
} else if (s.startsWith(ELEMENT_DECLARATION_START) || s.startsWith(ATTLIST_DECLARATION_START) || s.startsWith(NOTATION_DECLARATION_START)) {
|
|
167
|
+
try {
|
|
168
|
+
consumeDecl(s);
|
|
169
|
+
} catch (e) {
|
|
170
|
+
throw new XmlError.XmlError(
|
|
171
|
+
{ type: "UnknownToken", message: "Failed to consume declaration" },
|
|
172
|
+
s.genTextPosFrom(start)
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
throw new XmlError.XmlError(
|
|
177
|
+
{ type: "UnknownToken", message: "Failed to parse doctype" },
|
|
178
|
+
s.genTextPos()
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function parseDoctypeStart(s) {
|
|
184
|
+
s.advance(9);
|
|
185
|
+
s.consumeSpaces();
|
|
186
|
+
s.skipName();
|
|
187
|
+
s.skipSpaces();
|
|
188
|
+
parseExternalId(s);
|
|
189
|
+
s.skipSpaces();
|
|
190
|
+
const currCodeUnit = s.currCodeUnit();
|
|
191
|
+
if (currCodeUnit !== asciiConstants.OPEN_SQUARE_BRACKET && currCodeUnit !== asciiConstants.GREATER_THAN) {
|
|
192
|
+
throw new XmlError.XmlError(
|
|
193
|
+
{ type: "InvalidChar", expected: "'[' or '>'", actual: currCodeUnit },
|
|
194
|
+
s.genTextPos()
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function parseExternalId(s) {
|
|
199
|
+
if (s.startsWith(SYSTEM) || s.startsWith(PUBLIC)) {
|
|
200
|
+
const start = s.getPos();
|
|
201
|
+
s.advance(6);
|
|
202
|
+
const id = s.sliceBack(start);
|
|
203
|
+
s.consumeSpaces();
|
|
204
|
+
const quote = s.consumeQuote();
|
|
205
|
+
s.consumeCodeUnitsWhile((c) => c !== quote);
|
|
206
|
+
s.consumeCodeUnit(quote);
|
|
207
|
+
if (id === PUBLIC) {
|
|
208
|
+
s.consumeSpaces();
|
|
209
|
+
const _quote = s.consumeQuote();
|
|
210
|
+
s.consumeCodeUnitsWhile((c) => c !== _quote);
|
|
211
|
+
s.consumeCodeUnit(_quote);
|
|
212
|
+
}
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
function parseEntityDecl(s, tokenCallback) {
|
|
218
|
+
s.advance(8);
|
|
219
|
+
s.consumeSpaces();
|
|
220
|
+
const isGe = !s.tryConsumeCodeUnit(asciiConstants.PERCENT);
|
|
221
|
+
if (!isGe) {
|
|
222
|
+
s.consumeSpaces();
|
|
223
|
+
}
|
|
224
|
+
const name = s.consumeName();
|
|
225
|
+
s.consumeSpaces();
|
|
226
|
+
const definition = parseEntityDef(s, isGe);
|
|
227
|
+
if (definition !== null) {
|
|
228
|
+
tokenCallback({ type: "EntityDeclaration", name, definition });
|
|
229
|
+
}
|
|
230
|
+
s.skipSpaces();
|
|
231
|
+
s.consumeCodeUnit(asciiConstants.GREATER_THAN);
|
|
232
|
+
}
|
|
233
|
+
function parseEntityDef(s, isGe) {
|
|
234
|
+
const currCodeUnit = s.currCodeUnit();
|
|
235
|
+
if (currCodeUnit === asciiConstants.DOUBLE_QUOTE || currCodeUnit === asciiConstants.SINGLE_QUOTE) {
|
|
236
|
+
const quote = s.consumeQuote();
|
|
237
|
+
const start = s.getPos();
|
|
238
|
+
s.skipCodeUnitsWhile((c) => c !== quote);
|
|
239
|
+
const value = s.sliceBack(start);
|
|
240
|
+
s.consumeCodeUnit(quote);
|
|
241
|
+
return value;
|
|
242
|
+
} else if (currCodeUnit === asciiConstants.UPPERCASE_S || currCodeUnit === asciiConstants.UPPERCASE_P) {
|
|
243
|
+
if (parseExternalId(s)) {
|
|
244
|
+
if (isGe) {
|
|
245
|
+
s.skipSpaces();
|
|
246
|
+
if (s.startsWith(NDATA)) {
|
|
247
|
+
s.advance(5);
|
|
248
|
+
s.consumeSpaces();
|
|
249
|
+
s.skipName();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
throw new XmlError.XmlError({ type: "InvalidExternalID" }, s.genTextPos());
|
|
255
|
+
} else {
|
|
256
|
+
throw new XmlError.XmlError(
|
|
257
|
+
{ type: "InvalidChar", expected: "a quote, SYSTEM or PUBLIC", actual: currCodeUnit },
|
|
258
|
+
s.genTextPos()
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
function consumeDecl(s) {
|
|
263
|
+
s.skipCodeUnitsWhile((c) => c !== asciiConstants.GREATER_THAN);
|
|
264
|
+
s.consumeCodeUnit(asciiConstants.GREATER_THAN);
|
|
265
|
+
}
|
|
266
|
+
function parseElement(s, tokenCallback) {
|
|
267
|
+
const start = s.getPos();
|
|
268
|
+
s.advance(1);
|
|
269
|
+
const [prefix, local] = s.consumeQName();
|
|
270
|
+
tokenCallback({ type: "ElementStart", prefix, local, start });
|
|
271
|
+
let open = false;
|
|
272
|
+
while (!s.atEnd()) {
|
|
273
|
+
const hasSpace = s.startsWithSpace();
|
|
274
|
+
s.skipSpaces();
|
|
275
|
+
const _start = s.getPos();
|
|
276
|
+
const currCodeUnit = s.currCodeUnit();
|
|
277
|
+
if (currCodeUnit === asciiConstants.SLASH) {
|
|
278
|
+
s.advance(1);
|
|
279
|
+
s.consumeCodeUnit(asciiConstants.GREATER_THAN);
|
|
280
|
+
const range = s.rangeFrom(_start);
|
|
281
|
+
tokenCallback({ type: "ElementEnd", end: { type: "Empty" }, range });
|
|
282
|
+
break;
|
|
283
|
+
} else if (currCodeUnit === asciiConstants.GREATER_THAN) {
|
|
284
|
+
s.advance(1);
|
|
285
|
+
const range = s.rangeFrom(_start);
|
|
286
|
+
tokenCallback({ type: "ElementEnd", end: { type: "Open" }, range });
|
|
287
|
+
open = true;
|
|
288
|
+
break;
|
|
289
|
+
} else {
|
|
290
|
+
if (!hasSpace) {
|
|
291
|
+
throw new XmlError.XmlError(
|
|
292
|
+
{ type: "InvalidChar", expected: "a whitespace", actual: s.currCodeUnitUnchecked() },
|
|
293
|
+
s.genTextPos()
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
const [_prefix, _local, value] = parseAttribute(s);
|
|
297
|
+
const end = s.getPos();
|
|
298
|
+
tokenCallback({
|
|
299
|
+
type: "Attribute",
|
|
300
|
+
range: { start: _start, end },
|
|
301
|
+
prefix: _prefix,
|
|
302
|
+
local: _local,
|
|
303
|
+
value
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (open) {
|
|
308
|
+
if (s.config.rawTextElements != null) {
|
|
309
|
+
const qName = getQName.getQName(local, prefix);
|
|
310
|
+
if (s.config.rawTextElements.includes(qName)) {
|
|
311
|
+
parseContent(s, tokenCallback, `</${qName}>`);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
parseContent(s, tokenCallback);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
function parseAttribute(s) {
|
|
319
|
+
const [prefix, local] = s.consumeQName();
|
|
320
|
+
let value;
|
|
321
|
+
const start = s.getPos();
|
|
322
|
+
s.skipSpaces();
|
|
323
|
+
if (s.tryConsumeCodeUnit(asciiConstants.EQUALS)) {
|
|
324
|
+
s.skipSpaces();
|
|
325
|
+
const currCodeUnit = s.currCodeUnit();
|
|
326
|
+
if (currCodeUnit === asciiConstants.SINGLE_QUOTE || currCodeUnit === asciiConstants.DOUBLE_QUOTE) {
|
|
327
|
+
const quote = s.consumeQuote();
|
|
328
|
+
value = s.consumeCodeUnitsWhile((c) => c !== quote && c !== asciiConstants.LESS_THAN);
|
|
329
|
+
s.consumeCodeUnit(quote);
|
|
330
|
+
} else if (!s.config.strictDocument) {
|
|
331
|
+
value = s.consumeCodeUnitsWhile(
|
|
332
|
+
(c) => !utils.isXmlSpaceByte(c) && c !== asciiConstants.GREATER_THAN && c !== asciiConstants.SLASH && c !== asciiConstants.LESS_THAN
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
throw new XmlError.XmlError(
|
|
336
|
+
{ type: "InvalidChar", expected: "a quote", actual: currCodeUnit },
|
|
337
|
+
s.genTextPos()
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
} else if (!s.config.strictDocument) {
|
|
341
|
+
s.goTo(start);
|
|
342
|
+
value = "true";
|
|
343
|
+
} else {
|
|
344
|
+
throw new XmlError.XmlError(
|
|
345
|
+
{ type: "InvalidChar", expected: asciiConstants.EQUALS, actual: s.currCodeUnit() },
|
|
346
|
+
s.genTextPos()
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
return [prefix, local, value];
|
|
350
|
+
}
|
|
351
|
+
function parseContent(s, tokenCallback, parseContentUntil = asciiConstants.LESS_THAN) {
|
|
352
|
+
while (!s.atEnd()) {
|
|
353
|
+
if (typeof parseContentUntil === "number" ? s.currCodeUnit() === parseContentUntil : s.startsWith(parseContentUntil)) {
|
|
354
|
+
const nextCodeUnit = s.nextCodeUnit();
|
|
355
|
+
if (nextCodeUnit === asciiConstants.EXCLAMATION_MARK) {
|
|
356
|
+
if (s.startsWith(COMMENT_START)) {
|
|
357
|
+
parseComment(s, tokenCallback);
|
|
358
|
+
} else if (s.startsWith(CDATA_START)) {
|
|
359
|
+
parseCdata(s, tokenCallback);
|
|
360
|
+
} else {
|
|
361
|
+
throw new XmlError.XmlError(
|
|
362
|
+
{ type: "UnknownToken", message: "Failed to parse content" },
|
|
363
|
+
s.genTextPos()
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
} else if (nextCodeUnit === asciiConstants.QUESTION_MARK) {
|
|
367
|
+
parsePi(s, tokenCallback);
|
|
368
|
+
} else if (nextCodeUnit === asciiConstants.SLASH) {
|
|
369
|
+
parseCloseElement(s, tokenCallback);
|
|
370
|
+
break;
|
|
371
|
+
} else {
|
|
372
|
+
parseElement(s, tokenCallback);
|
|
373
|
+
}
|
|
374
|
+
} else {
|
|
375
|
+
parseText(s, tokenCallback, parseContentUntil);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function parseCdata(s, tokenCallback) {
|
|
380
|
+
const start = s.getPos();
|
|
381
|
+
s.advance(9);
|
|
382
|
+
const text = s.consumeCodeUnitsWhile(
|
|
383
|
+
(c, _s) => !(c === asciiConstants.CLOSE_SQUARE_BRACKET && _s.startsWith(CDATA_END))
|
|
384
|
+
);
|
|
385
|
+
s.skipString(CDATA_END);
|
|
386
|
+
const range = s.rangeFrom(start);
|
|
387
|
+
tokenCallback({ type: "Cdata", text, range });
|
|
388
|
+
}
|
|
389
|
+
function parseCloseElement(s, tokenCallback) {
|
|
390
|
+
const start = s.getPos();
|
|
391
|
+
s.advance(2);
|
|
392
|
+
const [prefix, local] = s.consumeQName();
|
|
393
|
+
s.skipSpaces();
|
|
394
|
+
s.consumeCodeUnit(asciiConstants.GREATER_THAN);
|
|
395
|
+
const range = s.rangeFrom(start);
|
|
396
|
+
tokenCallback({ type: "ElementEnd", end: { type: "Close", prefix, local }, range });
|
|
397
|
+
}
|
|
398
|
+
function parseText(s, tokenCallback, parseTextUntil = asciiConstants.LESS_THAN) {
|
|
399
|
+
const start = s.getPos();
|
|
400
|
+
const text = typeof parseTextUntil === "number" ? s.consumeCodeUnitsWhile((c) => c !== parseTextUntil) : s.consumeCodeUnitsWhile((_, _s) => !_s.startsWith(parseTextUntil));
|
|
401
|
+
if (text.includes(CDATA_END)) {
|
|
402
|
+
throw new XmlError.XmlError({ type: "InvalidCharacterData" }, s.genTextPos());
|
|
403
|
+
}
|
|
404
|
+
tokenCallback({ type: "Text", text, range: s.rangeFrom(start) });
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
exports.tokenize = tokenize;
|
|
408
|
+
exports.tokenizeXmlStream = tokenizeXmlStream;
|
|
@@ -1 +1,47 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var asciiConstants = require('./ascii-constants.js');
|
|
4
|
+
|
|
5
|
+
function isAsciiDigit(byte) {
|
|
6
|
+
return byte >= asciiConstants.ZERO && byte <= asciiConstants.NINE;
|
|
7
|
+
}
|
|
8
|
+
function isXmlNameStart(codePoint) {
|
|
9
|
+
if (codePoint == null) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (codePoint <= 128) {
|
|
13
|
+
return codePoint >= asciiConstants.UPPERCASE_A && codePoint <= asciiConstants.UPPERCASE_Z || codePoint >= asciiConstants.LOWERCASE_A && codePoint <= asciiConstants.LOWERCASE_Z || codePoint === asciiConstants.COLON || codePoint === asciiConstants.UNDERSCORE;
|
|
14
|
+
}
|
|
15
|
+
return codePoint >= 192 && codePoint <= 214 || codePoint >= 216 && codePoint <= 246 || codePoint >= 248 && codePoint <= 767 || codePoint >= 880 && codePoint <= 893 || codePoint >= 895 && codePoint <= 8191 || codePoint >= 8204 && codePoint <= 8205 || codePoint >= 8304 && codePoint <= 8591 || codePoint >= 11264 && codePoint <= 12271 || codePoint >= 12289 && codePoint <= 55295 || codePoint >= 63744 && codePoint <= 64975 || codePoint >= 65008 && codePoint <= 65533 || codePoint >= 65536 && codePoint <= 983039;
|
|
16
|
+
}
|
|
17
|
+
function isXmlName(codePoint) {
|
|
18
|
+
if (codePoint == null) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (codePoint <= 128) {
|
|
22
|
+
return isXmlNameByte(codePoint);
|
|
23
|
+
}
|
|
24
|
+
return codePoint === 183 || codePoint >= 192 && codePoint <= 214 || codePoint >= 216 && codePoint <= 246 || codePoint >= 248 && codePoint <= 767 || codePoint >= 768 && codePoint <= 879 || codePoint >= 880 && codePoint <= 893 || codePoint >= 895 && codePoint <= 8191 || codePoint >= 8204 && codePoint <= 8205 || codePoint >= 8255 && codePoint <= 8256 || codePoint >= 8304 && codePoint <= 8591 || codePoint >= 11264 && codePoint <= 12271 || codePoint >= 12289 && codePoint <= 55295 || codePoint >= 63744 && codePoint <= 64975 || codePoint >= 65008 && codePoint <= 65533 || codePoint >= 65536 && codePoint <= 983039;
|
|
25
|
+
}
|
|
26
|
+
function isXmlChar(codePoint) {
|
|
27
|
+
if (codePoint == null) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (codePoint < 32) {
|
|
31
|
+
return isXmlSpaceByte(codePoint);
|
|
32
|
+
}
|
|
33
|
+
return codePoint !== 65535 && codePoint !== 65534;
|
|
34
|
+
}
|
|
35
|
+
function isXmlSpaceByte(byte) {
|
|
36
|
+
return byte === asciiConstants.SPACE || byte === asciiConstants.HORIZONTAL_TAB || byte === asciiConstants.LINE_FEED || byte === asciiConstants.CARRIAGE_RETURN;
|
|
37
|
+
}
|
|
38
|
+
function isXmlNameByte(byte) {
|
|
39
|
+
return byte >= asciiConstants.ZERO && byte <= asciiConstants.NINE || byte >= asciiConstants.UPPERCASE_A && byte <= asciiConstants.UPPERCASE_Z || byte >= asciiConstants.LOWERCASE_A && byte <= asciiConstants.LOWERCASE_Z || byte === asciiConstants.COLON || byte === asciiConstants.UNDERSCORE || byte === asciiConstants.HYPHEN || byte === asciiConstants.PERIOD;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
exports.isAsciiDigit = isAsciiDigit;
|
|
43
|
+
exports.isXmlChar = isXmlChar;
|
|
44
|
+
exports.isXmlName = isXmlName;
|
|
45
|
+
exports.isXmlNameByte = isXmlNameByte;
|
|
46
|
+
exports.isXmlNameStart = isXmlNameStart;
|
|
47
|
+
exports.isXmlSpaceByte = isXmlSpaceByte;
|
|
@@ -1 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tokenToXml = require('./token-to-xml.js');
|
|
4
|
+
|
|
5
|
+
function tokensToXml(tokens) {
|
|
6
|
+
let xmlString = "";
|
|
7
|
+
tokens.forEach((token) => {
|
|
8
|
+
xmlString += tokenToXml.tokenToXml(token);
|
|
9
|
+
});
|
|
10
|
+
return xmlString;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
exports.tokensToXml = tokensToXml;
|
|
@@ -1 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tokenize = require('./tokenizer/tokenize.js');
|
|
4
|
+
|
|
5
|
+
function xmlToObject(xmlString, options = {}) {
|
|
6
|
+
const root = {
|
|
7
|
+
local: "root",
|
|
8
|
+
attributes: [],
|
|
9
|
+
content: []
|
|
10
|
+
};
|
|
11
|
+
const stack = [root];
|
|
12
|
+
tokenize.tokenize(
|
|
13
|
+
xmlString,
|
|
14
|
+
(token) => {
|
|
15
|
+
processTokenForObject(token, stack);
|
|
16
|
+
},
|
|
17
|
+
options
|
|
18
|
+
);
|
|
19
|
+
return root.content[0];
|
|
20
|
+
}
|
|
21
|
+
function processTokenForObject(token, stack) {
|
|
22
|
+
switch (token.type) {
|
|
23
|
+
case "ElementStart": {
|
|
24
|
+
const newNode = {
|
|
25
|
+
local: token.local,
|
|
26
|
+
prefix: token.prefix.length > 0 ? token.prefix : void 0,
|
|
27
|
+
attributes: [],
|
|
28
|
+
content: []
|
|
29
|
+
};
|
|
30
|
+
const currentNode = stack[stack.length - 1];
|
|
31
|
+
if (currentNode != null) {
|
|
32
|
+
currentNode.content.push(newNode);
|
|
33
|
+
}
|
|
34
|
+
stack.push(newNode);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
case "ElementEnd": {
|
|
38
|
+
if (token.end.type === "Close" || token.end.type === "Empty") {
|
|
39
|
+
stack.pop();
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case "Attribute": {
|
|
44
|
+
const currentNode = stack[stack.length - 1];
|
|
45
|
+
if (currentNode != null) {
|
|
46
|
+
currentNode.attributes.push({
|
|
47
|
+
local: token.local,
|
|
48
|
+
prefix: token.prefix.length > 0 ? token.prefix : void 0,
|
|
49
|
+
value: token.value
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
case "Text":
|
|
55
|
+
case "Cdata": {
|
|
56
|
+
const currentNode = stack[stack.length - 1];
|
|
57
|
+
if (currentNode != null) {
|
|
58
|
+
const trimmedText = token.text.trim();
|
|
59
|
+
if (trimmedText.length > 0) {
|
|
60
|
+
currentNode.content.push(token.text);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
exports.processTokenForObject = processTokenForObject;
|
|
69
|
+
exports.xmlToObject = xmlToObject;
|
|
@@ -1 +1,86 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var getQName = require('./get-q-name.js');
|
|
4
|
+
var tokenize = require('./tokenizer/tokenize.js');
|
|
5
|
+
|
|
6
|
+
function xmlToSimplifiedObject(xmlString, options = {}) {
|
|
7
|
+
const result = {};
|
|
8
|
+
const stack = [result];
|
|
9
|
+
tokenize.tokenize(
|
|
10
|
+
xmlString,
|
|
11
|
+
(token) => {
|
|
12
|
+
processTokenForSimplifiedObject(token, stack);
|
|
13
|
+
},
|
|
14
|
+
options
|
|
15
|
+
);
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
18
|
+
function processTokenForSimplifiedObject(token, stack) {
|
|
19
|
+
switch (token.type) {
|
|
20
|
+
case "ElementStart": {
|
|
21
|
+
const tagName = getQName.getQName(token.local, token.prefix);
|
|
22
|
+
const tagNameWithPrefix = `_${tagName}`;
|
|
23
|
+
const newNode = {};
|
|
24
|
+
const currentNode = stack[stack.length - 1];
|
|
25
|
+
if (currentNode != null) {
|
|
26
|
+
if (currentNode.content != null) {
|
|
27
|
+
newNode.tag = tagName;
|
|
28
|
+
currentNode.content.push(newNode);
|
|
29
|
+
} else if (currentNode.text != null) {
|
|
30
|
+
newNode.tag = tagName;
|
|
31
|
+
currentNode.content = [currentNode.text, newNode];
|
|
32
|
+
delete currentNode.text;
|
|
33
|
+
} else if (currentNode[tagNameWithPrefix] == null) {
|
|
34
|
+
currentNode[tagNameWithPrefix] = [newNode];
|
|
35
|
+
} else if (Array.isArray(currentNode[tagNameWithPrefix])) {
|
|
36
|
+
currentNode[tagNameWithPrefix].push(newNode);
|
|
37
|
+
} else {
|
|
38
|
+
currentNode[tagNameWithPrefix] = [currentNode[tagNameWithPrefix], newNode];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
stack.push(newNode);
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
case "ElementEnd": {
|
|
45
|
+
if (token.end.type === "Close" || token.end.type === "Empty") {
|
|
46
|
+
stack.pop();
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
case "Attribute": {
|
|
51
|
+
const currentNode = stack[stack.length - 1];
|
|
52
|
+
if (currentNode != null) {
|
|
53
|
+
const attrName = getQName.getQName(token.local, token.prefix);
|
|
54
|
+
if (currentNode.attributes != null) {
|
|
55
|
+
currentNode.attributes[attrName] = token.value;
|
|
56
|
+
} else {
|
|
57
|
+
currentNode.attributes = {
|
|
58
|
+
[attrName]: token.value
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case "Text":
|
|
65
|
+
case "Cdata": {
|
|
66
|
+
const currentNode = stack[stack.length - 1];
|
|
67
|
+
if (currentNode != null) {
|
|
68
|
+
const trimmedText = token.text.trim();
|
|
69
|
+
if (trimmedText.length > 0) {
|
|
70
|
+
if (currentNode.content != null) {
|
|
71
|
+
currentNode.content.push(trimmedText);
|
|
72
|
+
} else if (currentNode.text != null) {
|
|
73
|
+
currentNode.content = [currentNode.text, trimmedText];
|
|
74
|
+
delete currentNode.text;
|
|
75
|
+
} else {
|
|
76
|
+
currentNode.text = trimmedText;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
exports.processTokenForSimplifiedObject = processTokenForSimplifiedObject;
|
|
86
|
+
exports.xmlToSimplifiedObject = xmlToSimplifiedObject;
|
package/dist/esm/get-q-name.js
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
export { getQName } from './get-q-name.js';
|
|
2
|
+
export { select } from './selector/select.js';
|
|
3
|
+
export { TokenSelector } from './selector/TokenSelector.js';
|
|
4
|
+
export { EToCacheNodeProps, ETokenMatchCriteria, TokenSelectState } from './selector/TokenSelectState.js';
|
|
5
|
+
export { TokenSelectStateMachine } from './selector/TokenSelectStateMachine.js';
|
|
6
|
+
export { tokenToXml } from './token-to-xml.js';
|
|
7
|
+
export { AMPERSAND, CARRIAGE_RETURN, CLOSE_SQUARE_BRACKET, COLON, DOUBLE_QUOTE, EQUALS, EXCLAMATION_MARK, GREATER_THAN, HASH, HORIZONTAL_TAB, HYPHEN, LESS_THAN, LINE_FEED, LOWERCASE_A, LOWERCASE_F, LOWERCASE_X, LOWERCASE_Z, NINE, OPEN_SQUARE_BRACKET, PERCENT, PERIOD, QUESTION_MARK, SEMICOLON, SINGLE_QUOTE, SLASH, SPACE, UNDERSCORE, UPPERCASE_A, UPPERCASE_F, UPPERCASE_P, UPPERCASE_S, UPPERCASE_Z, ZERO } from './tokenizer/ascii-constants.js';
|
|
8
|
+
export { tokenize, tokenizeXmlStream } from './tokenizer/tokenize.js';
|
|
9
|
+
export { isAsciiDigit, isXmlChar, isXmlName, isXmlNameByte, isXmlNameStart, isXmlSpaceByte } from './tokenizer/utils.js';
|
|
10
|
+
export { XmlError } from './tokenizer/XmlError.js';
|
|
11
|
+
export { XmlStream } from './tokenizer/XmlStream.js';
|
|
12
|
+
export { tokensToXml } from './tokens-to-xml.js';
|
|
13
|
+
export { processTokenForObject, xmlToObject } from './xml-to-object.js';
|
|
14
|
+
export { processTokenForSimplifiedObject, xmlToSimplifiedObject } from './xml-to-simplified-object.js';
|