From cf5b20842dc46ab1a672cddc998b3f96d450d8a0 Mon Sep 17 00:00:00 2001
From: "libra-exla[bot]" <207437117+libra-exla[bot]@users.noreply.github.com>
Date: Mon, 1 Jun 2026 00:23:42 +0000
Subject: [PATCH 1/2] fix issue #2:
carriage-return-characters-r-are-incorrectly-rep
---
spec/cdata_spec.js | 71 +++++++++++++++++++++++++++++++
src/xmlparser/OrderedObjParser.js | 51 +++++++++++++++++++++-
2 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/spec/cdata_spec.js b/spec/cdata_spec.js
index 821179a5..6376744a 100644
--- a/spec/cdata_spec.js
+++ b/spec/cdata_spec.js
@@ -383,4 +383,75 @@ patronymic`;
// console.log(JSON.stringify(result,null,4));
expect(result).toEqual(expected);
});
+
+ it("should preserve carriage returns in CDATA", function () {
+ const xmlData = `
+
+
+
+
+
+
+`;
+
+ const expected = {
+ "properties": {
+ "property": [
+ {
+ "#value": "This is a carriage return \r...",
+ "@type": "string",
+ "@name": "x",
+ "@state": "changed"
+ },
+ {
+ "#value": "\r",
+ "@type": "string",
+ "@name": "y",
+ "@state": "changed"
+ }
+ ],
+ "@object": "",
+ "@engine": ""
+ }
+ };
+
+ const options = {
+ attributeNamePrefix: "@",
+ ignoreAttributes: false,
+ parseAttributeValue: false,
+ parseTagValue: false,
+ textNodeName: "#value",
+ };
+
+ const parser = new XMLParser(options);
+ let result = parser.parse(xmlData);
+
+ expect(result).toEqual(expected);
+ });
+
+ it("should normalize carriage returns outside CDATA", function () {
+ const xmlData = `x\ryx\r\ny`;
+
+ const expected = {
+ "root": {
+ "text": [
+ "x\ny",
+ "x\ny"
+ ],
+ "@_attr": "x\ny"
+ }
+ };
+
+ const options = {
+ ignoreAttributes: false,
+ parseAttributeValue: false,
+ parseTagValue: false,
+ trimValues: false,
+ };
+
+ const parser = new XMLParser(options);
+ let result = parser.parse(xmlData);
+
+ expect(result).toEqual(expected);
+ });
});
diff --git a/src/xmlparser/OrderedObjParser.js b/src/xmlparser/OrderedObjParser.js
index ec8d24d4..f3ea083c 100644
--- a/src/xmlparser/OrderedObjParser.js
+++ b/src/xmlparser/OrderedObjParser.js
@@ -274,8 +274,55 @@ function buildAttributesMap(attrStr, jPath, tagName, force = false) {
return attrs;
}
}
+function normalizeLineEndingsOutsideCDATA(xmlData) {
+ if (xmlData.indexOf("\r") === -1) return xmlData;
+
+ let normalizedXml = "";
+ let segmentStart = 0;
+ let insideTag = false;
+ let quoteChar = "";
+
+ for (let i = 0; i < xmlData.length; i++) {
+ const ch = xmlData[i];
+
+ if (insideTag) {
+ if (quoteChar) {
+ if (ch === quoteChar) quoteChar = "";
+ } else if (ch === '"' || ch === "'") {
+ quoteChar = ch;
+ } else if (ch === ">") {
+ insideTag = false;
+ }
+ } else if (ch === "<") {
+ if (xmlData.startsWith("", i + 9);
+ if (cdataEnd === -1) {
+ normalizedXml += xmlData.substring(i);
+ return normalizedXml;
+ }
+
+ const cdataCloseIndex = cdataEnd + 3;
+ normalizedXml += xmlData.substring(i, cdataCloseIndex);
+ i = cdataCloseIndex - 1;
+ segmentStart = cdataCloseIndex;
+ } else if (xmlData.startsWith("", i + 4);
+ if (commentEnd === -1) break;
+ i = commentEnd + 2;
+ } else {
+ insideTag = true;
+ }
+ }
+ }
+
+ normalizedXml += xmlData.substring(segmentStart).replace(/\r\n?/g, "\n");
+ return normalizedXml;
+}
+
const parseXml = function (xmlData) {
- xmlData = xmlData.replace(/\r\n?/g, "\n"); //TODO: remove this line
+ xmlData = normalizeLineEndingsOutsideCDATA(xmlData);
const xmlObj = new xmlNode('!xml');
let currentNode = xmlObj;
let textData = "";
@@ -835,4 +882,4 @@ function sanitizeName(name, options) {
return options.onDangerousProperty(name);
}
return name;
-}
\ No newline at end of file
+}
From e751e431329aad4491ff5006fd02f8bf468a0b5a Mon Sep 17 00:00:00 2001
From: Viraat Das
Date: Sun, 31 May 2026 18:42:56 -0700
Subject: [PATCH 2/2] test: remove redundant non-guarding carriage-return test
The 'should normalize carriage returns outside CDATA' test passed on
master both with and without the source change, so it guarded no
behavior. Keep the 'should preserve carriage returns in CDATA' test,
which exercises the actual fix.
---
spec/cdata_spec.js | 26 --------------------------
1 file changed, 26 deletions(-)
diff --git a/spec/cdata_spec.js b/spec/cdata_spec.js
index 6376744a..b0026582 100644
--- a/spec/cdata_spec.js
+++ b/spec/cdata_spec.js
@@ -428,30 +428,4 @@ patronymic`;
expect(result).toEqual(expected);
});
-
- it("should normalize carriage returns outside CDATA", function () {
- const xmlData = `x\ryx\r\ny`;
-
- const expected = {
- "root": {
- "text": [
- "x\ny",
- "x\ny"
- ],
- "@_attr": "x\ny"
- }
- };
-
- const options = {
- ignoreAttributes: false,
- parseAttributeValue: false,
- parseTagValue: false,
- trimValues: false,
- };
-
- const parser = new XMLParser(options);
- let result = parser.parse(xmlData);
-
- expect(result).toEqual(expected);
- });
});