1 |
|
2 |
|
3 | import { EasySAXParser } from '../js-libs/easysax';
|
4 | export class ParserEventType {
|
5 | }
|
6 | ParserEventType.StartElement = 'StartElement';
|
7 | ParserEventType.EndElement = 'EndElement';
|
8 | ParserEventType.Text = 'Text';
|
9 | ParserEventType.CDATA = 'CDATA';
|
10 | ParserEventType.Comment = 'Comment';
|
11 | export class ParserEvent {
|
12 | constructor(eventType, position, prefix, namespace, elementName, attributes, data) {
|
13 | this._eventType = eventType;
|
14 | this._position = position;
|
15 | this._prefix = prefix;
|
16 | this._namespace = namespace;
|
17 | this._elementName = elementName;
|
18 | this._attributes = attributes;
|
19 | this._data = data;
|
20 | }
|
21 | toString() {
|
22 | return JSON.stringify({
|
23 | eventType: this.eventType,
|
24 | position: this.position,
|
25 | prefix: this.prefix,
|
26 | namespace: this.namespace,
|
27 | elementName: this.elementName,
|
28 | attributes: this.attributes,
|
29 | data: this.data,
|
30 | });
|
31 | }
|
32 | get eventType() {
|
33 | return this._eventType;
|
34 | }
|
35 | get position() {
|
36 | return this._position;
|
37 | }
|
38 | get prefix() {
|
39 | return this._prefix;
|
40 | }
|
41 | get namespace() {
|
42 | return this._namespace;
|
43 | }
|
44 | get elementName() {
|
45 | return this._elementName;
|
46 | }
|
47 | get attributes() {
|
48 | return this._attributes;
|
49 | }
|
50 | get data() {
|
51 | return this._data;
|
52 | }
|
53 | }
|
54 | let _ampCodes;
|
55 | const _entitySearchRegEx = /&#(\d+);|&#x([0123456789abcdef]+);|&(\w+);/gi;
|
56 | function _generateAmpMap() {
|
57 | const objCodes = {
|
58 | Tab: 9,
|
59 | NewLine: 10,
|
60 | excl: 33,
|
61 | quot: 34,
|
62 | QUOT: 34,
|
63 | num: 35,
|
64 | dollar: 36,
|
65 | percent: 37,
|
66 | amp: 38,
|
67 | AMP: 38,
|
68 | apos: 39,
|
69 | lpar: 40,
|
70 | rpar: 41,
|
71 | ast: 42,
|
72 | midast: 42,
|
73 | plus: 43,
|
74 | comma: 44,
|
75 | period: 46,
|
76 | sol: 47,
|
77 | colon: 58,
|
78 | semi: 59,
|
79 | lt: 60,
|
80 | LT: 60,
|
81 | equals: 61,
|
82 | gt: 62,
|
83 | GT: 62,
|
84 | quest: 63,
|
85 | commat: 64,
|
86 | lsqb: 91,
|
87 | lbrack: 91,
|
88 | bsol: 92,
|
89 | rsqb: 92,
|
90 | rbrack: 92,
|
91 | Hat: 94,
|
92 | lowbar: 95,
|
93 | grave: 96,
|
94 | DiacriticalGrave: 96,
|
95 | lcub: 123,
|
96 | lbrace: 123,
|
97 | verbar: 124,
|
98 | vert: 124,
|
99 | VerticalLine: 124,
|
100 | rcub: 125,
|
101 | rbrace: 125,
|
102 | nbsp: 160,
|
103 | iexcl: 161,
|
104 | cent: 162,
|
105 | pound: 163,
|
106 | curren: 164,
|
107 | yen: 165,
|
108 | brvbar: 166,
|
109 | brkbar: 166,
|
110 | sect: 167,
|
111 | uml: 168,
|
112 | copy: 169,
|
113 | ordf: 170,
|
114 | laquo: 171,
|
115 | not: 172,
|
116 | shy: 173,
|
117 | reg: 174,
|
118 | macr: 175,
|
119 | hibar: 175,
|
120 | deg: 176,
|
121 | plusmn: 177,
|
122 | sup2: 178,
|
123 | sup3: 179,
|
124 | acute: 180,
|
125 | micro: 181,
|
126 | para: 182,
|
127 | middot: 183,
|
128 | cedil: 184,
|
129 | sup1: 185,
|
130 | ordm: 186,
|
131 | raquo: 187,
|
132 | frac14: 188,
|
133 | frac12: 189,
|
134 | frac34: 190,
|
135 | iquest: 191,
|
136 | Agrave: 192,
|
137 | Aacute: 193,
|
138 | Acirc: 194,
|
139 | Atilde: 195,
|
140 | Auml: 196,
|
141 | Aring: 197,
|
142 | AElig: 198,
|
143 | Ccedil: 199,
|
144 | Egrave: 200,
|
145 | Eacute: 201,
|
146 | Ecirc: 202,
|
147 | Euml: 203,
|
148 | Igrave: 204,
|
149 | Iacute: 205,
|
150 | Icirc: 206,
|
151 | Iuml: 207,
|
152 | ETH: 208,
|
153 | Dstrok: 208,
|
154 | Ntilde: 209,
|
155 | Ograve: 210,
|
156 | Oacute: 211,
|
157 | Ocirc: 212,
|
158 | Otilde: 213,
|
159 | Ouml: 214,
|
160 | times: 215,
|
161 | Oslash: 216,
|
162 | Ugrave: 217,
|
163 | Uacute: 218,
|
164 | Ucirc: 219,
|
165 | Uuml: 220,
|
166 | Yacute: 221,
|
167 | THORN: 222,
|
168 | szlig: 223,
|
169 | agrave: 224,
|
170 | aacute: 225,
|
171 | acirc: 226,
|
172 | atilde: 227,
|
173 | auml: 228,
|
174 | aring: 229,
|
175 | aelig: 230,
|
176 | ccedil: 231,
|
177 | egrave: 232,
|
178 | eacute: 233,
|
179 | ecirc: 234,
|
180 | euml: 235,
|
181 | igrave: 236,
|
182 | iacute: 237,
|
183 | icirc: 238,
|
184 | iuml: 239,
|
185 | eth: 240,
|
186 | ntilde: 241,
|
187 | ograve: 242,
|
188 | oacute: 243,
|
189 | ocirc: 244,
|
190 | otilde: 245,
|
191 | ouml: 246,
|
192 | divide: 247,
|
193 | oslash: 248,
|
194 | ugrave: 249,
|
195 | uacute: 250,
|
196 | ucirc: 251,
|
197 | uuml: 252,
|
198 | yacute: 253,
|
199 | thorn: 254,
|
200 | yuml: 255,
|
201 | fnof: 402,
|
202 | imped: 437,
|
203 | gacute: 501,
|
204 | jmath: 567,
|
205 | circ: 710,
|
206 | caron: 711,
|
207 | Hacek: 711,
|
208 | breve: 728,
|
209 | Breve: 728,
|
210 | dot: 729,
|
211 | DiacriticalDot: 729,
|
212 | ring: 730,
|
213 | ogon: 731,
|
214 | tilde: 732,
|
215 | DiacriticalTilde: 732,
|
216 | dblac: 733,
|
217 | DiacriticalDoubleAcute: 733,
|
218 | DownBreve: 785,
|
219 | UnderBar: 818,
|
220 | Alpha: 913,
|
221 | Beta: 914,
|
222 | Gamma: 915,
|
223 | Delta: 916,
|
224 | Epsilon: 917,
|
225 | Zeta: 918,
|
226 | Eta: 919,
|
227 | Theta: 920,
|
228 | Iota: 921,
|
229 | Kappa: 922,
|
230 | Lambda: 923,
|
231 | Mu: 924,
|
232 | Nu: 925,
|
233 | Xi: 926,
|
234 | Omicron: 927,
|
235 | Pi: 928,
|
236 | Rho: 929 ,
|
237 | Sigma: 931,
|
238 | Tau: 932,
|
239 | Upsilon: 933,
|
240 | Phi: 934,
|
241 | Chi: 935,
|
242 | Psi: 936,
|
243 | Omega: 937,
|
244 | alpha: 945,
|
245 | beta: 946,
|
246 | gamma: 947,
|
247 | delta: 948,
|
248 | epsilon: 949,
|
249 | epsiv: 949,
|
250 | varepsilon: 949,
|
251 | zeta: 950,
|
252 | eta: 951,
|
253 | theta: 952,
|
254 | iota: 953,
|
255 | kappa: 954,
|
256 | lambda: 955,
|
257 | mu: 956,
|
258 | nu: 957,
|
259 | xi: 958,
|
260 | omicron: 959,
|
261 | pi: 960,
|
262 | rho: 961,
|
263 | sigmaf: 962,
|
264 | sigmav: 962,
|
265 | varsigma: 962,
|
266 | sigma: 963,
|
267 | tau: 964,
|
268 | upsilon: 965,
|
269 | phi: 966,
|
270 | chi: 967,
|
271 | psi: 968,
|
272 | omega: 969,
|
273 | thetav: 977,
|
274 | vartheta: 977,
|
275 | thetasym: 977,
|
276 | Upsi: 978,
|
277 | upsih: 978,
|
278 | straightphi: 981,
|
279 | piv: 982,
|
280 | varpi: 982,
|
281 | Gammad: 988,
|
282 | gammad: 989,
|
283 | digamma: 989,
|
284 | kappav: 1008,
|
285 | varkappa: 1008,
|
286 | rhov: 1009,
|
287 | varrho: 1009,
|
288 | epsi: 1013,
|
289 | straightepsilon: 1013,
|
290 | bepsi: 1014,
|
291 | backepsilon: 1014,
|
292 | euro: 8364,
|
293 | trade: 8482,
|
294 | TRADE: 8482,
|
295 | forall: 8704,
|
296 | part: 8706,
|
297 | larr: 8592,
|
298 | rarr: 8593,
|
299 | hyphen: 8208,
|
300 | dash: 8208,
|
301 | ndash: 8211,
|
302 | mdash: 8212,
|
303 | horbar: 8213,
|
304 | Vert: 8214,
|
305 | Verbar: 8214,
|
306 | lsquo: 8216,
|
307 | OpenCurlyQuote: 8216,
|
308 | rsquo: 8217,
|
309 | rsquor: 8217,
|
310 | CloseCurlyQuote: 8217,
|
311 | lsquor: 8218,
|
312 | sbquo: 8218,
|
313 | ldquo: 8220,
|
314 | OpenCurlyDoubleQuote: 8220,
|
315 | rdquo: 8221,
|
316 | rdquor: 8221,
|
317 | CloseCurlyDoubleQuote: 8221,
|
318 | ldquor: 8222,
|
319 | bdquo: 8222,
|
320 | dagger: 8224,
|
321 | Dagger: 8225,
|
322 | ddagger: 8225,
|
323 | bull: 8226,
|
324 | bullet: 8226,
|
325 | nldr: 8229,
|
326 | hellip: 8230,
|
327 | mldr: 8230,
|
328 | hybull: 8259,
|
329 | tdot: 8411,
|
330 | TripleDot: 8411,
|
331 | DotDot: 8412,
|
332 | star: 9734,
|
333 | phone: 9742,
|
334 | spades: 9824,
|
335 | clubs: 9827,
|
336 | hearts: 9829,
|
337 | diams: 9830,
|
338 | female: 9792,
|
339 | male: 9794,
|
340 | check: 10003,
|
341 | checkmark: 10003,
|
342 | cross: 10007,
|
343 | VerticalSeparator: 10072,
|
344 | EmptySmallSquare: 9723,
|
345 | FilledSmallSquare: 9724,
|
346 | starf: 9733,
|
347 | bigstar: 9733,
|
348 | square: 9633,
|
349 | squ: 9633,
|
350 | Square: 9633,
|
351 | };
|
352 | const ampCodes = new Map();
|
353 | for (const key in objCodes) {
|
354 | if (objCodes.hasOwnProperty(key)) {
|
355 | ampCodes.set(key, objCodes[key]);
|
356 | }
|
357 | }
|
358 | return ampCodes;
|
359 | }
|
360 |
|
361 | if (global.__snapshot) {
|
362 | _ampCodes = _generateAmpMap();
|
363 | }
|
364 | function _HandleAmpEntities(found, decimalValue, hexValue, wordValue) {
|
365 | if (wordValue) {
|
366 | if (!_ampCodes) {
|
367 | _ampCodes = _generateAmpMap();
|
368 | }
|
369 | const res = _ampCodes.get(wordValue);
|
370 | if (res) {
|
371 | return String.fromCodePoint(res);
|
372 | }
|
373 |
|
374 | return found;
|
375 | }
|
376 | if (decimalValue) {
|
377 | return String.fromCodePoint(parseInt(decimalValue, 10));
|
378 | }
|
379 | return String.fromCodePoint(parseInt(hexValue, 16));
|
380 | }
|
381 | export class XmlParser {
|
382 | constructor(onEvent, onError, processNamespaces) {
|
383 | this._processNamespaces = processNamespaces;
|
384 | this._parser = new EasySAXParser();
|
385 | const that = this;
|
386 | this._parser.on('startNode', function (elem, attr, uq, tagend, str, pos) {
|
387 | let attributes = attr();
|
388 | if (attributes === true) {
|
389 |
|
390 | attributes = undefined;
|
391 | }
|
392 | if (attributes) {
|
393 | for (const key in attributes) {
|
394 | if (attributes.hasOwnProperty(key)) {
|
395 |
|
396 | attributes[key] = XmlParser._dereferenceEntities(attributes[key]);
|
397 | }
|
398 | }
|
399 | }
|
400 | let prefix = undefined;
|
401 | let namespace = undefined;
|
402 | let name = elem;
|
403 | if (that._processNamespaces) {
|
404 | const stackEntry = XmlParser._getNamespacesStackEntry(attributes);
|
405 | that._namespaceStack.push(stackEntry);
|
406 | const resolved = that._resolveNamespace(name);
|
407 | prefix = resolved.prefix;
|
408 | namespace = resolved.namespace;
|
409 | name = resolved.name;
|
410 | }
|
411 | onEvent(new ParserEvent(ParserEventType.StartElement, pos(), prefix, namespace, name, attributes, undefined));
|
412 | });
|
413 | this._parser.on('textNode', function (text, uq, pos) {
|
414 | const data = uq(XmlParser._dereferenceEntities(text));
|
415 | onEvent(new ParserEvent(ParserEventType.Text, pos(), undefined, undefined, undefined, undefined, data));
|
416 | });
|
417 | this._parser.on('endNode', function (elem, uq, tagstart, str, pos) {
|
418 | let prefix = undefined;
|
419 | let namespace = undefined;
|
420 | let name = elem;
|
421 | if (that._processNamespaces) {
|
422 | const resolved = that._resolveNamespace(name);
|
423 | prefix = resolved.prefix;
|
424 | namespace = resolved.namespace;
|
425 | name = resolved.name;
|
426 | }
|
427 | onEvent(new ParserEvent(ParserEventType.EndElement, pos(), prefix, namespace, name, undefined, undefined));
|
428 | if (that._processNamespaces) {
|
429 | that._namespaceStack.pop();
|
430 | }
|
431 | });
|
432 | this._parser.on('cdata', function (data, res, pos) {
|
433 | onEvent(new ParserEvent(ParserEventType.CDATA, pos(), undefined, undefined, undefined, undefined, data));
|
434 | });
|
435 | this._parser.on('comment', function (text, uq, pos) {
|
436 | onEvent(new ParserEvent(ParserEventType.Comment, pos(), undefined, undefined, undefined, undefined, text));
|
437 | });
|
438 | if (onError) {
|
439 | this._parser.on('error', function (msg, pos) {
|
440 | onError(new Error(msg), pos());
|
441 | });
|
442 | }
|
443 | }
|
444 | get angularSyntax() {
|
445 | return this._parser.angularSyntax;
|
446 | }
|
447 | set angularSyntax(value) {
|
448 | this._parser.angularSyntax = value;
|
449 | }
|
450 | parse(xmlString) {
|
451 | if (this._processNamespaces) {
|
452 | this._namespaceStack = [];
|
453 | }
|
454 | this._parser.parse(xmlString);
|
455 | }
|
456 | static _getNamespacesStackEntry(attributes) {
|
457 | const stackEntry = {};
|
458 | if (!attributes) {
|
459 | return stackEntry;
|
460 | }
|
461 | let attributeName;
|
462 | let namespacePrefix;
|
463 | for (const key in attributes) {
|
464 | if (!attributes.hasOwnProperty(key)) {
|
465 | continue;
|
466 | }
|
467 | attributeName = key;
|
468 | if (attributeName.indexOf('xmlns') !== 0) {
|
469 |
|
470 | continue;
|
471 | }
|
472 | namespacePrefix = '';
|
473 | if (attributeName.indexOf(':') !== -1) {
|
474 | namespacePrefix = attributeName.split(':')[1];
|
475 | }
|
476 | stackEntry[namespacePrefix] = attributes[key];
|
477 | }
|
478 | return stackEntry;
|
479 | }
|
480 | _resolveNamespace(fullName) {
|
481 | const result = {
|
482 | prefix: undefined,
|
483 | namespace: undefined,
|
484 | name: undefined,
|
485 | };
|
486 | result.prefix = '';
|
487 | if (fullName.indexOf(':') !== -1) {
|
488 | const split = fullName.split(':');
|
489 | result.prefix = split[0];
|
490 | result.name = split[1];
|
491 | }
|
492 | else {
|
493 | result.name = fullName;
|
494 | }
|
495 | let stackEntry;
|
496 | for (let i = this._namespaceStack.length - 1; i >= 0; i--) {
|
497 | stackEntry = this._namespaceStack[i];
|
498 | for (const key in stackEntry) {
|
499 | if (!stackEntry.hasOwnProperty(key)) {
|
500 | continue;
|
501 | }
|
502 | if (result.prefix === key) {
|
503 | result.namespace = stackEntry[key];
|
504 | return result;
|
505 | }
|
506 | }
|
507 | }
|
508 | return result;
|
509 | }
|
510 | static _dereferenceEntities(s) {
|
511 | s = String(s);
|
512 | if (s.length > 3 && s.indexOf('&') !== -1) {
|
513 | s = s.replace(_entitySearchRegEx, _HandleAmpEntities);
|
514 | }
|
515 | return s;
|
516 | }
|
517 | }
|
518 |
|
\ | No newline at end of file |