diff --git a/NEWS b/NEWS index 8d7dd5088127..423631bbcea7 100644 --- a/NEWS +++ b/NEWS @@ -30,6 +30,8 @@ PHP NEWS . Fixed Dom\HTMLDocument giving attributes the namespace of their element when a fragment is parsed with an xlink, xml or xmlns context element. (Ilia Alshanetsky) + . getElementById() now finds elements whose id attribute was set with + setAttribute()/setAttributeNS() on Dom\XMLDocument. (Ilia Alshanetsky) - Fileinfo: . Upgrade to file 5.48. (Weilin Du) diff --git a/ext/dom/element.c b/ext/dom/element.c index 5fcffaf42055..41a605169ffb 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -393,8 +393,7 @@ static void dom_check_register_attribute_id(xmlAttrPtr attr, php_libxml_ref_obj { dom_mark_ids_modified(document); - if (attr->atype != XML_ATTRIBUTE_ID && attr->doc->type == XML_HTML_DOCUMENT_NODE && attr->ns == NULL && xmlStrEqual(attr->name, BAD_CAST "id")) { - /* To respect XML's ID behaviour, we only do this registration for HTML documents. */ + if (attr->atype != XML_ATTRIBUTE_ID && attr->ns == NULL && xmlStrEqual(attr->name, BAD_CAST "id")) { attr->atype = XML_ATTRIBUTE_ID; } } @@ -447,9 +446,10 @@ PHP_METHOD(DOMElement, setAttribute) xmlAddChild((xmlNodePtr) attr, node); } else { attr = xmlSetNsProp(nodep, NULL, name_processed, BAD_CAST value); - if (EXPECTED(attr != NULL)) { - dom_check_register_attribute_id(attr, intern->document); - } + } + + if (EXPECTED(attr != NULL)) { + dom_check_register_attribute_id(attr, intern->document); } if (name_processed != BAD_CAST name) { diff --git a/ext/dom/tests/modern/xml/Document_getElementById_setAttribute.phpt b/ext/dom/tests/modern/xml/Document_getElementById_setAttribute.phpt new file mode 100644 index 000000000000..91edde084b93 --- /dev/null +++ b/ext/dom/tests/modern/xml/Document_getElementById_setAttribute.phpt @@ -0,0 +1,68 @@ +--TEST-- +Dom\XMLDocument::getElementById() after setting id with setAttribute() +--EXTENSIONS-- +dom +--FILE-- +appendChild($dom->createElement("root")); +$a = $dom->createElement("a"); +$dom->documentElement->appendChild($a); + +echo "--- After parsing ---\n"; +var_dump($dom->getElementById("x")?->nodeName); + +echo "--- After setAttribute ---\n"; +$a->setAttribute("id", "x"); +var_dump($dom->getElementById("x")?->nodeName); +var_dump($dom->getElementById("y")?->nodeName); + +echo "--- After changing the id value with setAttribute ---\n"; +$a->setAttribute("id", "y"); +var_dump($dom->getElementById("x")?->nodeName); +var_dump($dom->getElementById("y")?->nodeName); + +echo "--- After setAttributeNS ---\n"; +$a->setAttributeNS(null, "id", "z"); +var_dump($dom->getElementById("y")?->nodeName); +var_dump($dom->getElementById("z")?->nodeName); + +echo "--- After removing the attribute ---\n"; +$a->removeAttribute("id"); +var_dump($dom->getElementById("z")?->nodeName); + +echo "--- After setIdAttribute ---\n"; +$a->setAttribute("id", "w"); +$a->setIdAttribute("id", false); +var_dump($dom->getElementById("w")?->nodeName); + +echo "--- Parsed id attribute changed with setAttribute ---\n"; +$parsed = Dom\XMLDocument::createFromString(''); +$b = $parsed->documentElement->firstElementChild; +var_dump($parsed->getElementById("p")?->nodeName); +$b->setAttribute("id", "q"); +var_dump($parsed->getElementById("p")?->nodeName); +var_dump($parsed->getElementById("q")?->nodeName); + +?> +--EXPECT-- +--- After parsing --- +NULL +--- After setAttribute --- +string(1) "a" +NULL +--- After changing the id value with setAttribute --- +NULL +string(1) "a" +--- After setAttributeNS --- +NULL +string(1) "a" +--- After removing the attribute --- +NULL +--- After setIdAttribute --- +NULL +--- Parsed id attribute changed with setAttribute --- +NULL +NULL +string(1) "b"