From 9adedbb281f817c22d39e21022ad7d3e8ed29b11 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Mon, 24 Aug 2026 09:43:45 -0400 Subject: [PATCH] [DOM] Register ids of SVG and MathML elements in the HTML5 parser getElementById() relies on the parser registering id attributes in the document ID cache. The lexbor bridge only registered them when the attribute was in the HTML namespace, so the ids of SVG and MathML elements were invisible. Sibling audit: dom_check_register_attribute_id() and php_set_attribute_id() handle runtime attribute creation and are namespace-correct already. --- NEWS | 2 ++ ext/dom/html5_parser.c | 2 +- ...ent_getElementById_foreign_namespaces.phpt | 23 +++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 ext/dom/tests/modern/common/Document_getElementById_foreign_namespaces.phpt diff --git a/NEWS b/NEWS index d25d441ca8b5..e4b665b80efa 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,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) + . Dom\HTMLDocument::getElementById() now finds the ids of SVG and MathML + elements. (iliaal) - GD: . Fixed imageaffinematrixget() and imageaffinematrixconcat() reporting the diff --git a/ext/dom/html5_parser.c b/ext/dom/html5_parser.c index 34320a122f53..84a251c3687f 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' && (attr->node.ns == LXB_NS_HTML || attr->node.ns == LXB_NS_SVG || attr->node.ns == LXB_NS_MATH)) { 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/common/Document_getElementById_foreign_namespaces.phpt b/ext/dom/tests/modern/common/Document_getElementById_foreign_namespaces.phpt new file mode 100644 index 000000000000..742d07a1345f --- /dev/null +++ b/ext/dom/tests/modern/common/Document_getElementById_foreign_namespaces.phpt @@ -0,0 +1,23 @@ +--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, +]); +?> +--EXPECT-- +array(3) { + ["svg #s"]=> + string(3) "svg" + ["math #m"]=> + string(4) "math" + ["html #p"]=> + string(1) "P" +}