node-opcua-xml2json 2.51.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 (40) hide show
  1. package/.mocharc.yml +13 -0
  2. package/LICENSE +20 -0
  3. package/dist/source/definition_parser.d.ts +3 -0
  4. package/dist/source/definition_parser.js +84 -0
  5. package/dist/source/definition_parser.js.map +1 -0
  6. package/dist/source/extension_object_parser.d.ts +17 -0
  7. package/dist/source/extension_object_parser.js +234 -0
  8. package/dist/source/extension_object_parser.js.map +1 -0
  9. package/dist/source/fragment_cloner.d.ts +13 -0
  10. package/dist/source/fragment_cloner.js +41 -0
  11. package/dist/source/fragment_cloner.js.map +1 -0
  12. package/dist/source/fragment_cloner_parser.d.ts +8 -0
  13. package/dist/source/fragment_cloner_parser.js +17 -0
  14. package/dist/source/fragment_cloner_parser.js.map +1 -0
  15. package/dist/source/index.d.ts +6 -0
  16. package/dist/source/index.js +19 -0
  17. package/dist/source/index.js.map +1 -0
  18. package/dist/source/nodejs/xml2json_fs.d.ts +10 -0
  19. package/dist/source/nodejs/xml2json_fs.js +39 -0
  20. package/dist/source/nodejs/xml2json_fs.js.map +1 -0
  21. package/dist/source/xml2Json_pojo_tools.d.ts +19 -0
  22. package/dist/source/xml2Json_pojo_tools.js +89 -0
  23. package/dist/source/xml2Json_pojo_tools.js.map +1 -0
  24. package/dist/source/xml2json.d.ts +177 -0
  25. package/dist/source/xml2json.js +296 -0
  26. package/dist/source/xml2json.js.map +1 -0
  27. package/dist/source/xml2json_pojo.d.ts +7 -0
  28. package/dist/source/xml2json_pojo.js +29 -0
  29. package/dist/source/xml2json_pojo.js.map +1 -0
  30. package/package.json +40 -0
  31. package/pnpm-lock.yaml +77 -0
  32. package/source/definition_parser.ts +84 -0
  33. package/source/extension_object_parser.ts +276 -0
  34. package/source/fragment_cloner.ts +51 -0
  35. package/source/fragment_cloner_parser.ts +17 -0
  36. package/source/index.ts +6 -0
  37. package/source/nodejs/xml2json_fs.ts +43 -0
  38. package/source/xml2Json_pojo_tools.ts +98 -0
  39. package/source/xml2json.ts +394 -0
  40. package/source/xml2json_pojo.ts +27 -0
package/pnpm-lock.yaml ADDED
@@ -0,0 +1,77 @@
1
+ lockfileVersion: 5.3
2
+
3
+ specifiers:
4
+ bomstrip: ^0.1.4
5
+ ltx: ^3.0.0
6
+ node-opcua-assert: 2.42.0
7
+ node-opcua-debug: 2.42.0
8
+ node-opcua-nodesets: 2.41.1
9
+ node-opcua-utils: 2.44.0
10
+ should: ^13.2.3
11
+ xml-writer: ^1.7.0
12
+
13
+ dependencies:
14
+ bomstrip: 0.1.4
15
+ ltx: 3.0.0
16
+ node-opcua-assert: link:../node-opcua-assert
17
+ node-opcua-debug: link:../node-opcua-debug
18
+ node-opcua-utils: link:../node-opcua-utils
19
+ xml-writer: 1.7.0
20
+
21
+ devDependencies:
22
+ node-opcua-nodesets: link:../node-opcua-nodesets
23
+ should: 13.2.3
24
+
25
+ packages:
26
+
27
+ /bomstrip/0.1.4:
28
+ resolution: {integrity: sha1-aSNnOCHMVHEatlYtQIhSZVzBGys=}
29
+ dev: false
30
+
31
+ /ltx/3.0.0:
32
+ resolution: {integrity: sha512-bu3/4/ApUmMqVNuIkHaRhqVtEi6didYcBDIF56xhPRCzVpdztCipZ62CUuaxMlMBUzaVL93+4LZRqe02fuAG6A==}
33
+ engines: {node: '>= 12.4.0'}
34
+ dev: false
35
+
36
+ /should-equal/2.0.0:
37
+ resolution: {integrity: sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==}
38
+ dependencies:
39
+ should-type: 1.4.0
40
+ dev: true
41
+
42
+ /should-format/3.0.3:
43
+ resolution: {integrity: sha1-m/yPdPo5IFxT04w01xcwPidxJPE=}
44
+ dependencies:
45
+ should-type: 1.4.0
46
+ should-type-adaptors: 1.1.0
47
+ dev: true
48
+
49
+ /should-type-adaptors/1.1.0:
50
+ resolution: {integrity: sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==}
51
+ dependencies:
52
+ should-type: 1.4.0
53
+ should-util: 1.0.1
54
+ dev: true
55
+
56
+ /should-type/1.4.0:
57
+ resolution: {integrity: sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=}
58
+ dev: true
59
+
60
+ /should-util/1.0.1:
61
+ resolution: {integrity: sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==}
62
+ dev: true
63
+
64
+ /should/13.2.3:
65
+ resolution: {integrity: sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==}
66
+ dependencies:
67
+ should-equal: 2.0.0
68
+ should-format: 3.0.3
69
+ should-type: 1.4.0
70
+ should-type-adaptors: 1.1.0
71
+ should-util: 1.0.1
72
+ dev: true
73
+
74
+ /xml-writer/1.7.0:
75
+ resolution: {integrity: sha1-t28dWRwWomNOvbcDx729D9aBkGU=}
76
+ engines: {node: '>=0.4.0'}
77
+ dev: false
@@ -0,0 +1,84 @@
1
+ // <Definition Name="SomeName">
2
+ // <Field Name="Running" Value="0" dataType: [ValueRank="1"]>
3
+ // [<Description>text</Description>]
4
+ // <Field>
5
+ // </Definition>
6
+ import assert from "node-opcua-assert";
7
+ import { ReaderStateParserLike, XmlAttributes } from "./xml2json";
8
+
9
+ // <Definition Name="SomeName">
10
+ // <Field Name="Running" Value="0" dataType: [ValueRank="1"]>
11
+ // [<Description>text</Description>]
12
+ // <Field>
13
+ // </Definition>
14
+ //
15
+ // Or
16
+ //
17
+ // (IsOptionSet)
18
+ //
19
+ //
20
+ export const _definitionParser: ReaderStateParserLike = {
21
+ init(this: any, name: string, attrs: XmlAttributes) {
22
+ assert(!this.parent.definitionFields || this.parent.definitionFields.length === 0);
23
+ this.parent.definitionFields = [];
24
+ this.parent.definitionName = attrs.SymbolicName || attrs.Name;
25
+ this.array = this.parent.definitionFields;
26
+ this.isUnion = attrs.IsUnion === "true" ? true : false;
27
+ },
28
+ parser: {
29
+ Field: {
30
+ init(this: any) {
31
+ this.description = undefined;
32
+ },
33
+ parser: {
34
+ Description: {
35
+ finish(this: any) {
36
+ this.parent.description = this.text;
37
+ },
38
+ },
39
+ },
40
+ finish(this: any) {
41
+ const obj: any = {
42
+ name: this.attrs.Name,
43
+ };
44
+ if (this.attrs.DataType !== undefined) {
45
+ obj.dataType = this.attrs.DataType;
46
+ }
47
+ if (this.description) {
48
+ obj.description = this.description;
49
+ }
50
+ if (this.attrs.Value !== undefined) {
51
+ obj.value = parseInt(this.attrs.Value, 10);
52
+ }
53
+ if (this.attrs.ValueRank !== undefined) {
54
+ obj.valueRank = parseInt(this.attrs.ValueRank, 10);
55
+ } else {
56
+ // when not specified valueRank means Scalar and Scalar is -1
57
+ obj.valueRank = -1;
58
+ }
59
+ if (this.attrs.ArrayDimensions !== undefined) {
60
+ obj.arrayDimensions = this.attrs.ArrayDimensions.split(",").map((e: string) => parseInt(e, 10));
61
+ }
62
+
63
+ obj.isOptional = this.attrs.IsOptional === "true" ? true : false;
64
+
65
+ if (this.attrs.SymbolicName !== undefined) {
66
+ obj.symbolicName = this.attrs.SymbolicName;
67
+ }
68
+ this.parent.array.push(obj);
69
+ },
70
+ },
71
+ },
72
+ };
73
+ export const definitionReaderStateParser: ReaderStateParserLike = {
74
+ parser: {
75
+ Definition: _definitionParser,
76
+ },
77
+ endElement(this: any) {
78
+ this._pojo = {
79
+ name: this.definitionName,
80
+
81
+ fields: this.definitionFields,
82
+ };
83
+ },
84
+ };
@@ -0,0 +1,276 @@
1
+ import { ReaderState, ReaderStateParserLike, ParserLike, XmlAttributes } from "./xml2json";
2
+ import { lowerFirstLetter } from "node-opcua-utils";
3
+
4
+ function BasicType_parser(dataType: string, parseFunc: (this: any, text: string) => any): ParserLike {
5
+ const r: ReaderStateParserLike = {
6
+ init(this: any, elementName: string, attrs: XmlAttributes) {
7
+ this.value = undefined;
8
+ },
9
+ finish(this: any) {
10
+ this.value = parseFunc.call(this, this.text);
11
+ }
12
+ };
13
+ const _parser: ParserLike = {};
14
+ _parser[dataType] = r;
15
+ return _parser;
16
+ }
17
+
18
+ function ListOf(dataType: string, parseFunc: any) {
19
+ return {
20
+ init(this: any) {
21
+ this.value = [];
22
+ },
23
+
24
+ parser: BasicType_parser(dataType, parseFunc),
25
+
26
+ finish(this: any) {},
27
+ endElement(this: any, elementName: string) {
28
+ this.value.push(this.parser[elementName].value);
29
+ }
30
+ };
31
+ }
32
+
33
+ const localizedTextReader: ReaderStateParserLike = {
34
+ init(this: any) {
35
+ this.localizedText = {};
36
+ },
37
+ parser: {
38
+ Locale: {
39
+ finish(this: any) {
40
+ this.parent.localizedText = this.parent.localizedText || {};
41
+ this.parent.localizedText.locale = this.text.trim();
42
+ }
43
+ },
44
+ Text: {
45
+ finish(this: any) {
46
+ this.parent.localizedText = this.parent.localizedText || {};
47
+ this.parent.localizedText.text = this.text.trim();
48
+ }
49
+ }
50
+ },
51
+ finish(this: any) {
52
+ this.value = this.localizedText;
53
+ }
54
+ };
55
+
56
+ const partials: { [key: string]: ReaderStateParserLike } = {
57
+ LocalizedText: localizedTextReader,
58
+ String: {
59
+ finish(this: any) {
60
+ this.value = this.text;
61
+ }
62
+ },
63
+
64
+ Boolean: {
65
+ finish(this: any) {
66
+ this.value = this.text.toLowerCase() === "true";
67
+ }
68
+ },
69
+
70
+ ByteString: {
71
+ init(this: any) {
72
+ this.value = null;
73
+ },
74
+ finish(this: any) {
75
+ const base64text = this.text;
76
+ const byteString = Buffer.from(base64text, "base64");
77
+ this.value = byteString;
78
+ }
79
+ },
80
+
81
+ Float: {
82
+ finish(this: any) {
83
+ this.value = parseFloat(this.text);
84
+ }
85
+ },
86
+
87
+ Double: {
88
+ finish(this: any) {
89
+ this.value = parseFloat(this.text);
90
+ }
91
+ },
92
+
93
+ Int8: {
94
+ finish(this: any) {
95
+ this.value = parseInt(this.text, 10);
96
+ }
97
+ },
98
+
99
+ Int16: {
100
+ finish(this: any) {
101
+ this.value = parseInt(this.text, 10);
102
+ }
103
+ },
104
+ Int32: {
105
+ finish(this: any) {
106
+ this.value = parseInt(this.text, 10);
107
+ }
108
+ },
109
+ Int64: {
110
+ finish(this: any) {
111
+ this.value = parseInt(this.text, 10);
112
+ }
113
+ },
114
+
115
+ UInt8: {
116
+ finish(this: any) {
117
+ this.value = parseInt(this.text, 10);
118
+ }
119
+ },
120
+
121
+ UInt16: {
122
+ finish(this: any) {
123
+ this.value = parseInt(this.text, 10);
124
+ }
125
+ },
126
+ UInt32: {
127
+ finish(this: any) {
128
+ this.value = parseInt(this.text, 10);
129
+ }
130
+ },
131
+ UInt64: {
132
+ finish(this: any) {
133
+ this.value = parseInt(this.text, 10);
134
+ }
135
+ },
136
+
137
+ ListOfLocalizedText: {
138
+ init(this: any) {
139
+ this.value = [];
140
+ },
141
+ parser: { LocalizedText: localizedTextReader },
142
+ finish(this: any) {},
143
+ endElement(this: any /*element*/) {
144
+ this.value.push(this.parser.LocalizedText.value);
145
+ }
146
+ },
147
+
148
+ ListOfDouble: ListOf("Double", parseFloat),
149
+
150
+ ListOfFloat: ListOf("Float", parseFloat),
151
+
152
+ ListOfInt32: ListOf("Int32", parseInt),
153
+
154
+ ListOfInt16: ListOf("Int16", parseInt),
155
+
156
+ ListOfInt8: ListOf("Int8", parseInt),
157
+
158
+ ListOfUint32: ListOf("Uint32", parseInt),
159
+
160
+ ListOfUint16: ListOf("Uint16", parseInt),
161
+
162
+ ListOfUint8: ListOf("Uint8", parseInt)
163
+ };
164
+
165
+ interface Field {
166
+ dataType: any;
167
+ description?: string;
168
+ name: string;
169
+ value?: any;
170
+ valueRank?: number; // default is -1 => scalar
171
+ }
172
+
173
+ export interface Definition {
174
+ name: string;
175
+ fields: Field[];
176
+ }
177
+
178
+ export interface DefinitionMap {
179
+ findDefinition(name: string): Definition;
180
+ }
181
+
182
+ function _clone(a: any): any {
183
+ if (typeof a === "string" || typeof a === "number" || typeof a === "boolean") {
184
+ return a;
185
+ }
186
+ if (a instanceof Array) {
187
+ return a.map((x) => _clone(x));
188
+ }
189
+ return { ...a };
190
+ }
191
+
192
+ function _makeExtensionObjectReader(definitionName: string, definitionMap: DefinitionMap, readerMap: any): ReaderStateParserLike {
193
+ // is it a basic type ?
194
+ if (partials.hasOwnProperty(definitionName)) {
195
+ return partials[definitionName];
196
+ }
197
+
198
+ let reader: ReaderStateParserLike = readerMap[definitionName]!;
199
+
200
+ if (reader) {
201
+ return reader;
202
+ }
203
+ const definition = definitionMap.findDefinition(definitionName);
204
+ if (!definition) {
205
+ throw new Error("cannot find definition for " + definitionName);
206
+ }
207
+ reader = {
208
+ finish(this: any) {},
209
+ parser: {}
210
+ };
211
+
212
+ for (const field of definition.fields) {
213
+ const fieldReader = _makeExtensionObjectReader(field.dataType, definitionMap, readerMap);
214
+ if (!fieldReader) {
215
+ throw new Error(" Cannot find reader for dataType " + field.dataType);
216
+ }
217
+
218
+ if (field.valueRank === undefined || field.valueRank === -1) {
219
+ const parser = fieldReader;
220
+ if (!parser) {
221
+ throw new Error("??? " + field.dataType + " " + field.name);
222
+ }
223
+ reader.parser![field.name] = {
224
+ parser: fieldReader.parser,
225
+ // endElement: fieldReader.endElement,
226
+ finish(this: any) {
227
+ const elName = lowerFirstLetter(field.name);
228
+ fieldReader.finish!.call(this);
229
+ this.parent.value = this.parent.value || {};
230
+ this.parent.value[elName] = _clone(this.value);
231
+ }
232
+ };
233
+ } else if (field.valueRank === 1) {
234
+ const listReader: ReaderStateParserLike = {
235
+ init(this: any) {
236
+ this.value = [];
237
+ },
238
+ parser: {},
239
+ finish(this: any) {
240
+ const elName = lowerFirstLetter(this.name);
241
+ this.parent.value = this.parent.value || {};
242
+ this.parent.value[elName] = this.value;
243
+ this.value = undefined;
244
+ },
245
+ startElement(this: any, name: string, attrs: XmlAttributes) {
246
+ // empty
247
+ },
248
+ endElement(this: any, element: string) {
249
+ this.value.push(_clone(this.parser[element].value));
250
+ }
251
+ };
252
+ listReader.parser![field.dataType] = fieldReader;
253
+ reader.parser![field.name] = listReader;
254
+ } else {
255
+ throw new Error("Unsupported ValueRank !");
256
+ }
257
+ }
258
+ // xx const parser: ParserLike = {};
259
+ // xx parser[definition.name] = reader;
260
+ readerMap[definitionName] = reader;
261
+ return reader;
262
+ }
263
+
264
+ export function makeExtensionObjectReader(definitionName: string, definitionMap: DefinitionMap, readerMap: any) {
265
+ const reader1: ReaderStateParserLike = {
266
+ parser: {},
267
+ endElement(this: any) {
268
+ // console.log(this.parser[definitionName].value);
269
+ this._pojo = this.parser[definitionName].value;
270
+ }
271
+ };
272
+
273
+ reader1.parser![definitionName] = _makeExtensionObjectReader(definitionName, definitionMap, readerMap);
274
+
275
+ return new ReaderState(reader1);
276
+ }
@@ -0,0 +1,51 @@
1
+ import { Xml2Json, XmlAttributes, IReaderState } from "./xml2json";
2
+
3
+ interface XmlWriter {
4
+ startElement(elementName: string): this;
5
+
6
+ endElement(): this;
7
+
8
+ writeAttribute(attributeName: string, attributeValue: string | number): this;
9
+
10
+ writeComment(comment: string): this;
11
+
12
+ text(str: string): this;
13
+ }
14
+ const XMLWriter = require("xml-writer");
15
+
16
+ export class InternalFragmentClonerReaderState implements IReaderState {
17
+ private _xw: XmlWriter = new XMLWriter(true);
18
+ public value: any;
19
+ public initLevel: number = 0;
20
+ public engine?: Xml2Json;
21
+
22
+ public _on_startElement(level: number, elementName: string, attrs: XmlAttributes): void {
23
+ this._xw.startElement(elementName);
24
+ for (const [attName, attValue] of Object.entries(attrs)) {
25
+ this._xw.writeAttribute(attName, attValue);
26
+ }
27
+ }
28
+ public _on_endElement(level: number, elementName: string): void {
29
+ this._xw.endElement();
30
+ if (this.initLevel === level) {
31
+ this.value = this._xw.toString();
32
+ this.engine!._demote(this, this.engine!.currentLevel, elementName);
33
+ this.engine = undefined;
34
+ this._on_finish();
35
+ }
36
+ }
37
+ public _on_init(elementName: string, attrs: XmlAttributes, parent: IReaderState, level: number, engine: Xml2Json): void {
38
+ this.engine = engine;
39
+ this.initLevel = level;
40
+ this._xw = new XMLWriter(true);
41
+ this._xw.startElement(elementName);
42
+ for (const [attName, attValue] of Object.entries(attrs)) {
43
+ this._xw.writeAttribute(attName, attValue);
44
+ }
45
+ }
46
+ public _on_finish(): void {}
47
+ public _on_endElement2(level: number, elementName: string): void {}
48
+ public _on_text(text: string): void {
49
+ this._xw.text(text);
50
+ }
51
+ }
@@ -0,0 +1,17 @@
1
+ import { InternalFragmentClonerReaderState } from "./fragment_cloner";
2
+ import { XmlAttributes } from "./xml2json";
3
+
4
+ export class FragmentClonerParser {
5
+ public value: any;
6
+ private _cloneFragment?: InternalFragmentClonerReaderState;
7
+ constructor() {}
8
+
9
+ public startElement(this: any, elementName: string, attrs: XmlAttributes) {
10
+ this._cloneFragment = new InternalFragmentClonerReaderState();
11
+ this.engine!._promote(this._cloneFragment, this.engine!.currentLevel, elementName, attrs);
12
+ }
13
+ public finish() {
14
+ this.value = this._cloneFragment!.value;
15
+ this._cloneFragment!.value = null;
16
+ }
17
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./xml2json";
2
+ export * from "./fragment_cloner";
3
+ export * from "./xml2json_pojo";
4
+ export * from "./fragment_cloner_parser";
5
+ export * from "./extension_object_parser";
6
+ export * from "./definition_parser";
@@ -0,0 +1,43 @@
1
+ import * as fs from "fs";
2
+ import { Callback, SimpleCallback, Xml2Json } from "../xml2json";
3
+
4
+ export class Xml2JsonFs extends Xml2Json {
5
+ /**
6
+ * @method parse
7
+ * @async
8
+ * @param xmlFile - the name of the xml file to parse.
9
+ */
10
+ public parse(xmlFile: string): Promise<any>;
11
+ public parse(xmlFile: string, callback: Callback<any> | SimpleCallback): void;
12
+ public parse(xmlFile: string, callback?: Callback<any> | SimpleCallback): any {
13
+ if (!callback) {
14
+ throw new Error("internal error");
15
+ }
16
+ const readWholeFile = true;
17
+ if (readWholeFile) {
18
+ // slightly faster but require more memory ..
19
+ fs.readFile(xmlFile, (err: Error | null, data: Buffer) => {
20
+ if (err) {
21
+ return callback(err);
22
+ }
23
+ if (data[0] === 0xef && data[1] === 0xbb && data[2] === 0xbf) {
24
+ data = data.slice(3);
25
+ }
26
+ const dataAsString = data.toString();
27
+ const parser = this._prepareParser(callback);
28
+ parser.write(dataAsString);
29
+ parser.end();
30
+ });
31
+ } else {
32
+ const Bomstrip = require("bomstrip");
33
+
34
+ const parser = this._prepareParser(callback);
35
+
36
+ fs.createReadStream(xmlFile, { autoClose: true, encoding: "utf8" }).pipe(new Bomstrip()).pipe(parser);
37
+ }
38
+ }
39
+ }
40
+ // tslint:disable:no-var-requires
41
+ const thenify = require("thenify");
42
+ const opts = { multiArgs: false };
43
+ Xml2JsonFs.prototype.parse = thenify.withCallback(Xml2JsonFs.prototype.parse, opts);
@@ -0,0 +1,98 @@
1
+ import { IReaderState, ReaderState, ReaderStateBase, ReaderStateParser, Xml2Json, XmlAttributes } from "./xml2json";
2
+ import { lowerFirstLetter } from "node-opcua-utils";
3
+ export type withPojoLambda = (name: string, pojo: any) => void;
4
+
5
+ export class ReaderState2 extends ReaderStateBase {
6
+ public _stack: any;
7
+ public _pojo: any;
8
+ public _element: any;
9
+ public text: string;
10
+
11
+ public _withPojo: withPojoLambda;
12
+
13
+ private parent?: IReaderState;
14
+ private engine?: Xml2Json;
15
+ private initLevel: number = 0;
16
+
17
+ constructor() {
18
+ super();
19
+ this._pojo = {};
20
+ this._stack = [];
21
+ this._element = {};
22
+ this.text = "";
23
+ this.parent = undefined;
24
+ this._withPojo = (pojo: any) => {
25
+ /* empty */
26
+ };
27
+ }
28
+
29
+ public _on_init(elementName: string, attrs: XmlAttributes, parent: IReaderState, level: number, engine: Xml2Json): void {
30
+ this.parent = parent;
31
+ this.engine = engine;
32
+ this.initLevel = level;
33
+ if (this._stack.length === 0) {
34
+ this._pojo = {};
35
+ this._element = this._pojo;
36
+ }
37
+ }
38
+
39
+ public _on_finish() {
40
+ /* empy */
41
+ }
42
+
43
+ public _on_startElement(level: number, elementName: string, attrs: XmlAttributes): void {
44
+ this._stack.push(this._element);
45
+
46
+ if (elementName.match(/^ListOf/)) {
47
+ elementName = elementName.substring(6);
48
+ const elName = lowerFirstLetter(elementName);
49
+ if (this._element instanceof Array) {
50
+ const array: any[] = [];
51
+ this._element.push(array);
52
+ this._element = array;
53
+ } else {
54
+ this._element[elName] = [];
55
+ this._element = this._element[elName];
56
+ }
57
+ } else {
58
+ const elName = lowerFirstLetter(elementName);
59
+ if (this._element instanceof Array) {
60
+ const obj = {};
61
+ this._element.push(obj);
62
+ this._element = obj;
63
+ } else {
64
+ this._element[elName] = {};
65
+ this._element = this._element[elName];
66
+ }
67
+ }
68
+ }
69
+
70
+ public _on_endElement2(level: number, elementName: string): void {
71
+ /* empty */
72
+ }
73
+
74
+ public _on_endElement(level: number, elementName: string): void {
75
+ this._element = this._stack.pop();
76
+ if (this.text.length > 0 && this._element) {
77
+ const elName = lowerFirstLetter(elementName);
78
+ this._element[elName] = this.text;
79
+ // this.engine!._pojo = this._pojo;
80
+ } else {
81
+ const elName = lowerFirstLetter(elementName);
82
+ if (this.initLevel === level) {
83
+ if (this._withPojo) {
84
+ if (this.text.length) {
85
+ this._withPojo.call(null, elName, this.text);
86
+ } else {
87
+ this._withPojo.call(null, elName, this._pojo);
88
+ }
89
+ }
90
+ }
91
+ }
92
+ this.text = "";
93
+ }
94
+
95
+ public _on_text(text: string): void {
96
+ this.text = text;
97
+ }
98
+ }