Работа над XmlParser

This commit is contained in:
Book Pauk
2022-11-07 21:50:38 +07:00
parent e4571faf39
commit 8f4dec510c
2 changed files with 96 additions and 8 deletions

View File

@@ -352,7 +352,9 @@ class XmlParser extends NodeBase {
return this.selectFirst(selector, self);
}
toJson(format = false) {
toJson(options = {}) {
const {format = false} = options;
if (format)
return JSON.stringify(this.rawNodes, null, 2);
else
@@ -395,7 +397,11 @@ class XmlParser extends NodeBase {
if (node.attrs) {
for (const [attrName, attrValue] of node.attrs) {
attrs += ` ${attrName}="${attrValue}"`;
if (typeof(attrValue) === 'string')
attrs += ` ${attrName}="${attrValue}"`;
else
if (attrValue)
attrs += ` ${attrName}`;
}
}
@@ -410,11 +416,11 @@ class XmlParser extends NodeBase {
close = (deepType === NODE ? ' '.repeat(depth) : '') + close + '\n';
}
} else if (node.type === TEXT) {
body = node.value;
body = node.value || '';
} else if (node.type === CDATA) {
//
body = `<![CDATA[${node.value || ''}]]>`;
} else if (node.type === COMMENT) {
//
body = `<!--${node.value || ''}-->`;
}
result += `${open}${body}${close}`;
@@ -429,7 +435,89 @@ class XmlParser extends NodeBase {
return out;
}
fromSrtring() {
fromString(xmlString, options = {}, pickNode = () => true) {
const parsed = [];
const root = this.createNode(parsed);
let node = root;
let route = '';
let routeStack = [];
let ignoreNode = false;
const {lowerCase = false, whiteSpace = false} = options;
const onStartNode = (tag, tail, singleTag, cutCounter, cutTag) => {// eslint-disable-line no-unused-vars
if (tag == '?xml')
return;
route += `/${tag}`;
ignoreNode = !pickNode(route);
const newNode = this.createNode(tag);
routeStack.push({tag, route, ignoreNode, node: newNode});
if (ignoreNode)
return;
if (tail) {
const parsedAttrs = sax.getAttrsSync(tail, lowerCase);
const attrs = new Map();
for (const attr of parsedAttrs.values()) {
attrs.set(attr.fn, attr.value);
}
if (attrs.size)
newNode.attrs = attrs;
}
if (!node.value)
node.value = [];
node.value.push(newNode.raw);
node = newNode;
};
const onEndNode = (tag, tail, singleTag, cutCounter, cutTag) => {// eslint-disable-line no-unused-vars
if (routeStack.length && routeStack[routeStack.length - 1].tag === tag) {
routeStack.pop();
if (routeStack.length) {
const last = routeStack[routeStack.length - 1];
route = last.route;
ignoreNode = last.ignoreNode;
node = last.node;
} else {
route = '';
ignoreNode = false;
node = root;
}
}
}
const onTextNode = (text, cutCounter, cutTag) => {// eslint-disable-line no-unused-vars
if (ignoreNode)
return;
if (!whiteSpace && text.trim() == '')
return;
if (!node.value)
node.value = [];
node.value.push(this.createText(text).raw);
};
const onCdata = (tagData, cutCounter, cutTag) => {// eslint-disable-line no-unused-vars
}
const onComment = (tagData, cutCounter, cutTag) => {// eslint-disable-line no-unused-vars
}
sax.parseSync(xmlString, {
onStartNode, onEndNode, onTextNode, onCdata, onComment, lowerCase
});
this.rawNodes = parsed;
}
}

View File

@@ -281,7 +281,7 @@ async function parse(xstr, options) {
}
function getAttrsSync(tail, lowerCase = true) {
let result = {};
let result = new Map();
let name = '';
let value = '';
let vOpen = '';
@@ -300,7 +300,7 @@ function getAttrsSync(tail, lowerCase = true) {
[ns, name] = fn.split(':');
}
result[name] = {value, ns, fn};
result.set(fn, {value, ns, name, fn});
}
name = '';
value = '';