From 8c991345847e4b050d746a3efc28ddfa7115a130 Mon Sep 17 00:00:00 2001 From: Magdalena Stojek Date: Wed, 12 Mar 2025 14:23:53 +0100 Subject: [PATCH] QDom: Fix setAttributeNode() to properly replace existing attributes This fix ensures that QDomElement::setAttributeNode() correctly replaces an existing attribute with the same name. Previously, calling setAttributeNode() with a new attribute of the same name resulted in both the old and new attributes being present, violating the expected behavior described in the documentation. Fixes: QTBUG-15125 Pick-to: 6.9 6.8 6.5 Change-Id: Ibdda37a65f6e754d9f7e68e725d3438bbb2d9e0c Reviewed-by: Mate Barany --- src/xml/dom/qdom.cpp | 10 +++++++--- tests/auto/xml/dom/qdom/tst_qdom.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 9daf13f377c..7bfe6cd5cc7 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -4123,14 +4123,18 @@ QDomAttrPrivate* QDomElementPrivate::attributeNodeNS(const QString& nsURI, const QDomAttrPrivate* QDomElementPrivate::setAttributeNode(QDomAttrPrivate* newAttr) { - QDomNodePrivate* n = m_attr->namedItem(newAttr->nodeName()); + if (!newAttr) + return nullptr; + + QDomNodePrivate* foundAttr = m_attr->namedItem(newAttr->nodeName()); + if (foundAttr) + m_attr->removeNamedItem(newAttr->nodeName()); // Referencing is done by the maps m_attr->setNamedItem(newAttr); - newAttr->setParent(this); - return static_cast(n); + return static_cast(foundAttr); } QDomAttrPrivate* QDomElementPrivate::setAttributeNodeNS(QDomAttrPrivate* newAttr) diff --git a/tests/auto/xml/dom/qdom/tst_qdom.cpp b/tests/auto/xml/dom/qdom/tst_qdom.cpp index 8138de1fce3..2c62e6fa1a8 100644 --- a/tests/auto/xml/dom/qdom/tst_qdom.cpp +++ b/tests/auto/xml/dom/qdom/tst_qdom.cpp @@ -89,6 +89,7 @@ private slots: void normalizeAttributes() const; void serializeWeirdEOL() const; void reparentAttribute() const; + void replaceAttribute() const; void serializeNamespaces() const; void flagInvalidNamespaces() const; void flagUndeclaredNamespace() const; @@ -1999,6 +2000,33 @@ void tst_QDom::reparentAttribute() const QVERIFY(attr.parentNode() == ele); } +void tst_QDom::replaceAttribute() const +{ + QDomImplementation impl; + QDomDocument doc(impl.createDocument("", "docName", QDomDocumentType())); + + QDomElement root = doc.createElement("root"); + doc.appendChild(root); + + QDomAttr attr1 = doc.createAttribute("firstAttribute"); + attr1.setValue("true"); + auto nullAttr = root.setAttributeNode(attr1); + QVERIFY(nullAttr.isNull()); + QVERIFY(root.hasAttribute("firstAttribute")); + QCOMPARE(root.attributeNode("firstAttribute").value(), "true"); + + QDomAttr attr2 = doc.createAttribute("firstAttribute"); + attr2.setValue("false"); + root.setAttributeNode(attr2); + QCOMPARE(root.attributeNode("firstAttribute").value(), "false"); + + QDomAttr attr3 = doc.createAttribute("secondAttribute"); + attr3.setValue("123"); + root.setAttributeNode(attr3); + QVERIFY(root.hasAttribute("secondAttribute")); + QCOMPARE(root.attributeNode("secondAttribute").value(), "123"); +} + void tst_QDom::serializeNamespaces() const { const char *const input = ""