UNPKG

13.9 kBJavaScriptView Raw
1// TODO: Delete `nativescript-core/xml/xml.js` from source control after
2// https://github.com/NativeScript/nativescript-dev-webpack/issues/932
3import { EasySAXParser } from '../js-libs/easysax';
4export class ParserEventType {
5}
6ParserEventType.StartElement = 'StartElement';
7ParserEventType.EndElement = 'EndElement';
8ParserEventType.Text = 'Text';
9ParserEventType.CDATA = 'CDATA';
10ParserEventType.Comment = 'Comment';
11export 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}
54let _ampCodes;
55const _entitySearchRegEx = /&#(\d+);|&#x([0123456789abcdef]+);|&(\w+);/gi;
56function _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 /* 930 is not real */,
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 /* Skipped Codes 1015 - 1119 */ 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// android-specific implementation, which pre-populates the map to get it saved into the heap blob
361if (global.__snapshot) {
362 _ampCodes = _generateAmpMap();
363}
364function _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 // Invalid word; so we just return it
374 return found;
375 }
376 if (decimalValue) {
377 return String.fromCodePoint(parseInt(decimalValue, 10));
378 }
379 return String.fromCodePoint(parseInt(hexValue, 16));
380}
381export 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 //HACK: For some reason easysax returns the true literal when an element has no attributes.
390 attributes = undefined;
391 }
392 if (attributes) {
393 for (const key in attributes) {
394 if (attributes.hasOwnProperty(key)) {
395 // Convert entities such as > to >
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)); // Decode entity references such as < and >
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 // This is a normal attribute, so go on.
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//# sourceMappingURL=index.js.map
\No newline at end of file