Skip to content

Commit

Permalink
Fix issue in case when namespace has no prefix (#330)
Browse files Browse the repository at this point in the history
  • Loading branch information
git9527 authored Jul 8, 2023
1 parent 131bcf9 commit ec309ec
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ npm-debug.log
.eslintcache
.nyc_output/
coverage/
.idea
9 changes: 8 additions & 1 deletion lib/c14n-canonicalization.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
}
Expand Down
36 changes: 17 additions & 19 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}
Expand All @@ -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.
Expand Down Expand Up @@ -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);
}
}

Expand Down
26 changes: 26 additions & 0 deletions test/c14n-non-exclusive-unit-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
"<root xmlns='bbb'><child1><ds:child2 xmlns:ds='ddd'><ds:child3></ds:child3></ds:child2></child1></root>";
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 = "<root xmlns='bbb'><child1><child2 xmlns='ddd'></child2></child1></root>";
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 = "<root xmlns:aaa='bbb'><child1><child2></child2></child1></root>";
Expand Down Expand Up @@ -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 =
"<root xmlns='bbb'><child1><cc:child2 xmlns:cc='ddd'><cc:child3></cc:child3></cc:child2></child1></root>";
const xpath = "//*[local-name()='child3']";
const expected = '<cc:child3 xmlns="bbb" xmlns:cc="ddd"></cc:child3>';

test_C14nCanonicalization(xml, xpath, expected);
});
});

0 comments on commit ec309ec

Please sign in to comment.