From 88331e6a5d6dba7276c83ed687cdd2757a0d4d21 Mon Sep 17 00:00:00 2001 From: git9527 <398816613@qq.com> Date: Thu, 6 Jul 2023 22:14:55 +0800 Subject: [PATCH] fix issue in case when namespace has no prefix --- .gitignore | 1 + lib/c14n-canonicalization.js | 9 ++++++- lib/utils.js | 36 +++++++++++++--------------- test/c14n-non-exclusive-unit-test.js | 26 ++++++++++++++++++++ 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 5df09413..5d1431c9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ npm-debug.log .eslintcache .nyc_output/ coverage/ +.idea diff --git a/lib/c14n-canonicalization.js b/lib/c14n-canonicalization.js index 04686724..373dffa5 100644 --- a/lib/c14n-canonicalization.js +++ b/lib/c14n-canonicalization.js @@ -149,7 +149,14 @@ class C14nCanonicalization { nsListToRender.sort(this.nsCompare); //render namespaces - res.push(...nsListToRender.map((attr) => ` xmlns:${attr.prefix}="${attr.namespaceURI}"`)); + res.push( + ...nsListToRender.map((attr) => { + if (attr.prefix) { + return ` xmlns:${attr.prefix}="${attr.namespaceURI}"`; + } + return ` xmlns="${attr.namespaceURI}"`; + }) + ); return { rendered: res.join(""), newDefaultNs: newDefaultNs }; } diff --git a/lib/utils.js b/lib/utils.js index e14ea3ed..df1705d7 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -138,9 +138,9 @@ function collectAncestorNamespaces(node, nsArray) { if (parent.attributes && parent.attributes.length > 0) { for (let i = 0; i < parent.attributes.length; i++) { const attr = parent.attributes[i]; - if (attr && attr.nodeName && attr.nodeName.search(/^xmlns:/) !== -1) { + if (attr && attr.nodeName && attr.nodeName.search(/^xmlns:?/) !== -1) { nsArray.push({ - prefix: attr.nodeName.replace(/^xmlns:/, ""), + prefix: attr.nodeName.replace(/^xmlns:?/, ""), namespaceURI: attr.nodeValue, }); } @@ -150,6 +150,17 @@ function collectAncestorNamespaces(node, nsArray) { return collectAncestorNamespaces(parent, nsArray); } +function findNSPrefix(subset) { + const subsetAttributes = subset.attributes; + for (let k = 0; k < subsetAttributes.length; k++) { + const nodeName = subsetAttributes[k].nodeName; + if (nodeName.search(/^xmlns:?/) !== -1) { + return nodeName.replace(/^xmlns:?/, ""); + } + } + return subset.prefix || ""; +} + /** * Extract ancestor namespaces in order to import it to root of document subset * which is being canonicalized for non-exclusive c14n. @@ -185,23 +196,10 @@ function findAncestorNs(doc, docSubsetXpath, namespaceResolver) { // Remove namespaces which are already declared in the subset with the same prefix const returningNs = []; - const subsetAttributes = docSubset[0].attributes; - for (let j = 0; j < ancestorNsWithoutDuplicate.length; j++) { - let isUnique = true; - for (let k = 0; k < subsetAttributes.length; k++) { - const nodeName = subsetAttributes[k].nodeName; - if (nodeName.search(/^xmlns:/) === -1) { - continue; - } - const prefix = nodeName.replace(/^xmlns:/, ""); - if (ancestorNsWithoutDuplicate[j].prefix === prefix) { - isUnique = false; - break; - } - } - - if (isUnique) { - returningNs.push(ancestorNsWithoutDuplicate[j]); + const subsetNsPrefix = findNSPrefix(docSubset[0]); + for (const ancestorNs of ancestorNsWithoutDuplicate) { + if (ancestorNs.prefix !== subsetNsPrefix) { + returningNs.push(ancestorNs); } } diff --git a/test/c14n-non-exclusive-unit-test.js b/test/c14n-non-exclusive-unit-test.js index 3d54d80b..1cbaaa47 100644 --- a/test/c14n-non-exclusive-unit-test.js +++ b/test/c14n-non-exclusive-unit-test.js @@ -97,6 +97,23 @@ describe("C14N non-exclusive canonicalization tests", function () { test_findAncestorNs(xml, xpath, expected); }); + it("findAncestorNs: Should find namespace without prefix", function () { + const xml = + ""; + const xpath = "//*[local-name()='child2']"; + const expected = [{ prefix: "", namespaceURI: "bbb" }]; + + test_findAncestorNs(xml, xpath, expected); + }); + + it("findAncestorNs: Should not find namespace when both has no prefix", function () { + const xml = ""; + const xpath = "//*[local-name()='child2']"; + const expected = []; + + test_findAncestorNs(xml, xpath, expected); + }); + // Tests for c14nCanonicalization it("C14n: Correctly picks up root ancestor namespace", function () { const xml = ""; @@ -181,4 +198,13 @@ describe("C14N non-exclusive canonicalization tests", function () { test_C14nCanonicalization(xml, xpath, expected); }); + + it("C14n: should not has colon when parent namespace has no prefix", function () { + const xml = + ""; + const xpath = "//*[local-name()='child3']"; + const expected = ''; + + test_C14nCanonicalization(xml, xpath, expected); + }); });