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);
+ });
});