From 25a8e7d156d14db9ba6c6b3758cf23322beb073e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 6 Sep 2026 10:56:24 -0400 Subject: [PATCH] dom: register unprefixed id attributes from foreign content in HTML The HTML5 parser bridge only marked an id attribute as XML_ATTRIBUTE_ID when the attribute sat in the HTML namespace, so ids on SVG and MathML elements never reached getElementById(). The condition the bridge wants is that the attribute itself is unprefixed, which lxml_attr->ns already records: it is only set for the xmlns, xlink and xml namespaces. Closes GH-23598 --- NEWS | 2 ++ ext/dom/html5_parser.c | 2 +- ...ent_getElementById_foreign_namespaces.phpt | 26 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 ext/dom/tests/modern/html/parser/HTMLDocument_getElementById_foreign_namespaces.phpt diff --git a/NEWS b/NEWS index 1cc265f02e8d..5ca7a0f6457c 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,8 @@ PHP NEWS that still have a live wrapper). (iliaal) . Fixed a use-after-free when Dom\Element::setAttributeNS() replaces the value of an attribute whose child still has a live wrapper. (iliaal) + . Fixed Dom\HTMLDocument::getElementById() not finding ids of SVG and + MathML elements. (Ilia Alshanetsky) - GD: . Fixed imageaffinematrixget() and imageaffinematrixconcat() reporting the diff --git a/ext/dom/html5_parser.c b/ext/dom/html5_parser.c index 34320a122f53..dbae8df5dbab 100644 --- a/ext/dom/html5_parser.c +++ b/ext/dom/html5_parser.c @@ -274,7 +274,7 @@ static lexbor_libxml2_bridge_status lexbor_libxml2_bridge_convert( last_added_attr = lxml_attr; /* xmlIsID does some other stuff too that is irrelevant here. */ - if (local_name_length == 2 && local_name[0] == 'i' && local_name[1] == 'd' && attr->node.ns == LXB_NS_HTML) { + if (local_name_length == 2 && local_name[0] == 'i' && local_name[1] == 'd' && lxml_attr->ns == NULL) { if (xmlAddID(NULL, lxml_doc, value, lxml_attr) == 0) { /* If the ID already exists, the ID attribute still needs to be marked as an ID. */ lxml_attr->atype = XML_ATTRIBUTE_ID; diff --git a/ext/dom/tests/modern/html/parser/HTMLDocument_getElementById_foreign_namespaces.phpt b/ext/dom/tests/modern/html/parser/HTMLDocument_getElementById_foreign_namespaces.phpt new file mode 100644 index 000000000000..e9f4f7ad8bb2 --- /dev/null +++ b/ext/dom/tests/modern/html/parser/HTMLDocument_getElementById_foreign_namespaces.phpt @@ -0,0 +1,26 @@ +--TEST-- +Dom\HTMLDocument::getElementById() finds ids of SVG and MathML elements +--EXTENSIONS-- +dom +--FILE-- +

'; +$d = Dom\HTMLDocument::createFromString($html, LIBXML_NOERROR); +var_dump([ + 'svg #s' => $d->getElementById('s')?->tagName, + 'math #m' => $d->getElementById('m')?->tagName, + 'html #p' => $d->getElementById('p')?->tagName, + 'xml:id #r' => $d->getElementById('r')?->tagName, +]); +?> +--EXPECT-- +array(4) { + ["svg #s"]=> + string(3) "svg" + ["math #m"]=> + string(4) "math" + ["html #p"]=> + string(1) "P" + ["xml:id #r"]=> + NULL +}