diff --git a/server/core/xml/ObjectNavigator.js b/server/core/xml/ObjectNavigator.js new file mode 100644 index 0000000..b2331f5 --- /dev/null +++ b/server/core/xml/ObjectNavigator.js @@ -0,0 +1,111 @@ +class ObjectNavigator { + constructor(raw = null) { + if (Array.isArray(raw)) + this.raw = raw; + else + this.raw = [raw]; + } + + makeSelector(selector) { + const result = []; + selector = selector.trim(); + + //последний индекс не учитывется, только если не задан явно + if (selector && selector[selector.length - 1] == ']') + selector += '/'; + + const levels = selector.split('/'); + + for (const level of levels) { + const [name, indexPart] = level.split('['); + let index = 0; + if (indexPart) { + const i = indexPart.indexOf(']'); + index = parseInt(indexPart.substring(0, i), 10) || 0; + } + + result.push({name, index}); + } + + if (result.length); + result[result.length - 1].last = true; + + return result; + } + + select(selector = '') { + selector = this.makeSelector(selector); + + let raw = this.raw; + for (const s of selector) { + if (s.name) { + raw = raw[0]; + if (typeof(raw) === 'object' && !Array.isArray(raw)) + raw = raw[s.name]; + else + raw = null; + + if (raw !== null && !s.last) { + if (Array.isArray(raw)) + raw = raw[s.index]; + else if (s.index > 0) + raw = null; + } + } else { + raw = raw[s.index]; + } + + if (raw === undefined || raw === null) { + raw = null; + break; + } + + if (!Array.isArray(raw)) + raw = [raw]; + } + + if (raw === null) + return null; + + const result = []; + for (const r of raw) + result.push(new ObjectNavigator(r)); + + return result; + } + + $$(selector) { + return this.select(selector); + } + + $(selector) { + const res = this.select(selector); + return (res !== null && res.length ? res[0] : null); + } + + get value() { + return (this.raw.length ? this.raw[0] : null); + } + + text(selector = '') { + const res = this.$(`${selector}/*TEXT`); + return (res ? res.value : null); + } + + comment(selector = '') { + const res = this.$(`${selector}/*COMMENT`); + return (res ? res.value : null); + } + + cdata(selector = '') { + const res = this.$(`${selector}/*CDATA`); + return (res ? res.value : null); + } + + attrs(selector = '') { + const res = this.$(`${selector}/*ATTRS`); + return (res ? res.value : null); + } +} + +module.exports = ObjectNavigator; \ No newline at end of file diff --git a/server/core/xml/XmlParser.js b/server/core/xml/XmlParser.js index fedc362..456629b 100644 --- a/server/core/xml/XmlParser.js +++ b/server/core/xml/XmlParser.js @@ -1,4 +1,5 @@ const sax = require('./sax'); +const ObjectNavigator = require('./ObjectNavigator'); //node types const NODE = 1; @@ -78,11 +79,11 @@ class NodeBase { } class NodeObject extends NodeBase { - constructor(rawNode) { + constructor(raw = null) { super(); - if (rawNode) - this.raw = rawNode; + if (raw) + this.raw = raw; else this.raw = []; } @@ -748,6 +749,10 @@ class XmlParser extends NodeBase { return this; } + + navigator() { + return new ObjectNavigator(this.toObject()); + } } module.exports = XmlParser; \ No newline at end of file