Skip to content

Commit 88331e6

Browse files
committed
fix issue in case when namespace has no prefix
1 parent 131bcf9 commit 88331e6

File tree

4 files changed

+52
-20
lines changed

4 files changed

+52
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ npm-debug.log
1010
.eslintcache
1111
.nyc_output/
1212
coverage/
13+
.idea

lib/c14n-canonicalization.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,14 @@ class C14nCanonicalization {
149149
nsListToRender.sort(this.nsCompare);
150150

151151
//render namespaces
152-
res.push(...nsListToRender.map((attr) => ` xmlns:${attr.prefix}="${attr.namespaceURI}"`));
152+
res.push(
153+
...nsListToRender.map((attr) => {
154+
if (attr.prefix) {
155+
return ` xmlns:${attr.prefix}="${attr.namespaceURI}"`;
156+
}
157+
return ` xmlns="${attr.namespaceURI}"`;
158+
})
159+
);
153160

154161
return { rendered: res.join(""), newDefaultNs: newDefaultNs };
155162
}

lib/utils.js

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ function collectAncestorNamespaces(node, nsArray) {
138138
if (parent.attributes && parent.attributes.length > 0) {
139139
for (let i = 0; i < parent.attributes.length; i++) {
140140
const attr = parent.attributes[i];
141-
if (attr && attr.nodeName && attr.nodeName.search(/^xmlns:/) !== -1) {
141+
if (attr && attr.nodeName && attr.nodeName.search(/^xmlns:?/) !== -1) {
142142
nsArray.push({
143-
prefix: attr.nodeName.replace(/^xmlns:/, ""),
143+
prefix: attr.nodeName.replace(/^xmlns:?/, ""),
144144
namespaceURI: attr.nodeValue,
145145
});
146146
}
@@ -150,6 +150,17 @@ function collectAncestorNamespaces(node, nsArray) {
150150
return collectAncestorNamespaces(parent, nsArray);
151151
}
152152

153+
function findNSPrefix(subset) {
154+
const subsetAttributes = subset.attributes;
155+
for (let k = 0; k < subsetAttributes.length; k++) {
156+
const nodeName = subsetAttributes[k].nodeName;
157+
if (nodeName.search(/^xmlns:?/) !== -1) {
158+
return nodeName.replace(/^xmlns:?/, "");
159+
}
160+
}
161+
return subset.prefix || "";
162+
}
163+
153164
/**
154165
* Extract ancestor namespaces in order to import it to root of document subset
155166
* which is being canonicalized for non-exclusive c14n.
@@ -185,23 +196,10 @@ function findAncestorNs(doc, docSubsetXpath, namespaceResolver) {
185196

186197
// Remove namespaces which are already declared in the subset with the same prefix
187198
const returningNs = [];
188-
const subsetAttributes = docSubset[0].attributes;
189-
for (let j = 0; j < ancestorNsWithoutDuplicate.length; j++) {
190-
let isUnique = true;
191-
for (let k = 0; k < subsetAttributes.length; k++) {
192-
const nodeName = subsetAttributes[k].nodeName;
193-
if (nodeName.search(/^xmlns:/) === -1) {
194-
continue;
195-
}
196-
const prefix = nodeName.replace(/^xmlns:/, "");
197-
if (ancestorNsWithoutDuplicate[j].prefix === prefix) {
198-
isUnique = false;
199-
break;
200-
}
201-
}
202-
203-
if (isUnique) {
204-
returningNs.push(ancestorNsWithoutDuplicate[j]);
199+
const subsetNsPrefix = findNSPrefix(docSubset[0]);
200+
for (const ancestorNs of ancestorNsWithoutDuplicate) {
201+
if (ancestorNs.prefix !== subsetNsPrefix) {
202+
returningNs.push(ancestorNs);
205203
}
206204
}
207205

test/c14n-non-exclusive-unit-test.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,23 @@ describe("C14N non-exclusive canonicalization tests", function () {
9797
test_findAncestorNs(xml, xpath, expected);
9898
});
9999

100+
it("findAncestorNs: Should find namespace without prefix", function () {
101+
const xml =
102+
"<root xmlns='bbb'><child1><ds:child2 xmlns:ds='ddd'><ds:child3></ds:child3></ds:child2></child1></root>";
103+
const xpath = "//*[local-name()='child2']";
104+
const expected = [{ prefix: "", namespaceURI: "bbb" }];
105+
106+
test_findAncestorNs(xml, xpath, expected);
107+
});
108+
109+
it("findAncestorNs: Should not find namespace when both has no prefix", function () {
110+
const xml = "<root xmlns='bbb'><child1><child2 xmlns='ddd'></child2></child1></root>";
111+
const xpath = "//*[local-name()='child2']";
112+
const expected = [];
113+
114+
test_findAncestorNs(xml, xpath, expected);
115+
});
116+
100117
// Tests for c14nCanonicalization
101118
it("C14n: Correctly picks up root ancestor namespace", function () {
102119
const xml = "<root xmlns:aaa='bbb'><child1><child2></child2></child1></root>";
@@ -181,4 +198,13 @@ describe("C14N non-exclusive canonicalization tests", function () {
181198

182199
test_C14nCanonicalization(xml, xpath, expected);
183200
});
201+
202+
it("C14n: should not has colon when parent namespace has no prefix", function () {
203+
const xml =
204+
"<root xmlns='bbb'><child1><cc:child2 xmlns:cc='ddd'><cc:child3></cc:child3></cc:child2></child1></root>";
205+
const xpath = "//*[local-name()='child3']";
206+
const expected = '<cc:child3 xmlns="bbb" xmlns:cc="ddd"></cc:child3>';
207+
208+
test_C14nCanonicalization(xml, xpath, expected);
209+
});
184210
});

0 commit comments

Comments
 (0)