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 <mate.barany@qt.io>
This commit is contained in:
Magdalena Stojek 2025-03-12 14:23:53 +01:00
parent 1b9cf55117
commit 8c99134584
2 changed files with 35 additions and 3 deletions

View File

@ -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<QDomAttrPrivate *>(n);
return static_cast<QDomAttrPrivate *>(foundAttr);
}
QDomAttrPrivate* QDomElementPrivate::setAttributeNodeNS(QDomAttrPrivate* newAttr)

View File

@ -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 = "<doc xmlns:b='http://example.com/'>"