Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions spec/stopNodes_spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use strict";

import { XMLParser, XMLValidator } from "../src/fxp.js";
import { Expression } from "path-expression-matcher";

describe("XMLParser StopNodes", function () {
it("should support single stopNode with namespace and removeNSPrefix set", function () {
Expand Down Expand Up @@ -473,4 +474,58 @@ describe("XMLParser StopNodes", function () {
expect(result).toEqual(expected);

});
for (const preserveOrder of [false, true]) {
it(`should use stop-node paths in updateTag with preserveOrder=${preserveOrder}`, function () {
const paths = [];
const parser = new XMLParser({
preserveOrder,
stopNodes: ["root.skip", "root.keep"],
updateTag(tagName, jPath) {
paths.push([tagName, jPath]);
if (jPath === "root.skip") return false;
if (jPath === "root.keep") return "renamed";
return tagName;
}
});

const result = parser.parse("<root><skip><nested/></skip><keep><nested/></keep><after/></root>");
const expected = preserveOrder
? [{ root: [{ renamed: [{ "#text": "<nested/>" }] }, { after: [] }] }]
: { root: { renamed: "<nested/>", after: "" } };

expect(result).toEqual(expected);
expect(paths).toEqual([
["root", "root"],
["skip", "root.skip"],
["keep", "root.keep"],
["after", "root.after"]
]);
});
}

for (const item of ['<item id="2"/>', '<item id="2">']) {
it(`should pass the current matcher for an empty stop node: ${item}`, function () {
const expression = new Expression("root.item[id=2]");
const paths = [];
const parser = new XMLParser({
ignoreAttributes: false,
jPath: false,
unpairedTags: ["item"],
stopNodes: ["root.item"],
updateTag(tagName, matcher, attrs) {
paths.push(matcher.toString());
if (matcher.matches(expression)) {
expect(attrs).toEqual({ "@_id": "2" });
return "matched";
}
return tagName;
}
});

expect(parser.parse(`<root>${item}<after/></root>`))
.toEqual({ root: { matched: { "@_id": "2" }, after: "" } });
expect(paths).toEqual(["root", "root.item", "root.after"]);
});
}

});
5 changes: 3 additions & 2 deletions src/xmlparser/OrderedObjParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,11 +532,12 @@ const parseXml = function (xmlData) {
// For stop nodes, store raw content as-is without any processing
childNode.add(options.textNodeName, tagContent);

// Keep the stop node in the matcher until updateTag has been called.
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);

this.matcher.pop(); // Pop the stop node tag
this.isCurrentNodeStopNode = false; // Reset flag

this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);

if (options.captureMetaData) {
currentNode.addEndIndex(i + 1);
}
Expand Down