diff --git a/lib/saxes.js b/lib/saxes.js index a00e0c53..c7b38f8f 100644 --- a/lib/saxes.js +++ b/lib/saxes.js @@ -939,6 +939,7 @@ ${XML_NAMESPACE}.`); } } + const seen = new Set(); // Note: do not apply default ns to attributes: // http://www.w3.org/TR/REC-xml-names/#defaulting for (const [name, value] of this.attribList) { @@ -952,6 +953,12 @@ ${XML_NAMESPACE}.`); uri, }; + const eqname = `{${uri}}${local}`; + if (seen.has(eqname)) { + this.fail(`Duplicate attribute: ${eqname}`); + } + seen.add(eqname); + // if there's any attributes with an undefined namespace, // then fail on them now. if (prefix && prefix !== "xmlns" && !uri) { @@ -966,6 +973,9 @@ ${XML_NAMESPACE}.`); else { for (const [name, value] of this.attribList) { const a = { name, value }; + if (this.tag.attributes[name]) { + this.fail(`Duplicate attribute: ${name}.`); + } this.tag.attributes[name] = value; this.emitNode("onattribute", a); } diff --git a/test/duplicate-attribute.js b/test/duplicate-attribute.js index 4c806cc6..d86caaf2 100644 --- a/test/duplicate-attribute.js +++ b/test/duplicate-attribute.js @@ -9,6 +9,7 @@ require(".").test({ attributes: {}, }], ["attribute", { name: "id", value: "hello" }], + ["error", "Duplicate attribute: id.\nLine: 0\nColumn: 28\nChar: >"], ["attribute", { name: "id", value: "there" }], ["opentag", { name: "span",