Conversation
c2bb921 to
25a8e7d
Compare
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 phpGH-23598
|
|
||
| /* 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) { |
There was a problem hiding this comment.
| if (local_name_length == 2 && local_name[0] == 'i' && local_name[1] == 'd' && lxml_attr->ns == NULL) { | |
| if (local_name_length == 2 && local_name[0] == 'i' && local_name[1] == 'd') { |
There was a problem hiding this comment.
That also registers a genuinely namespaced id. lxml_attr->ns is non-NULL once a fragment is parsed into a foreign context:
$d = Dom\HTMLDocument::createEmpty();
$z = $d->createElementNS('http://www.w3.org/1999/xlink', 'z');
$d->appendChild($z);
$z->innerHTML = '<z id="q"></z>';
var_dump($d->getElementById('q'));Without the check that returns the element, with it NULL. The test didn't cover the case, which is why the guard read as redundant; pinned in 3e45b39.
There was a problem hiding this comment.
what about this test ?
--TEST--
Dom\HTMLDocument::getElementById() finds ids of SVG and MathML elements
--EXTENSIONS--
dom
--FILE--
<?php
$html = '<!DOCTYPE html><html><body><svg id="s"><rect xml:id="r"/></svg><math id="m"></math><p id="p"></p></body></html>';
$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,
]);
/* An unprefixed id is in no namespace whatever namespace its element is in. */
$d2 = Dom\HTMLDocument::createEmpty();
$z = $d2->createElementNS('http://www.w3.org/1999/xlink', 'z');
$d2->appendChild($z);
$z->innerHTML = '<z id="q"></z>';
var_dump($d2->getElementById('q')?->tagName);
?>
--EXPECT--
array(4) {
["svg #s"]=>
string(3) "svg"
["math #m"]=>
string(4) "math"
["html #p"]=>
string(1) "P"
["xml:id #r"]=>
NULL
}
string(1) "Z"then it might need ... && !attr->node.prefix) wdyt ?
There was a problem hiding this comment.
Ugh, you're right and my last answer was wrong. That id isn't namespaced, it's mislabeled: lexbor initializes every attribute node with its element's namespace, and before_append_attr is wired only for SVG and MathML, so in an xlink, xml or xmlns fragment context the same branch also turned foo="1" into xlink:foo.
That is a second defect alongside the id one, so both are fixed here: the three namespace branches now require a prefix or the bare xmlns declaration, and the id check reads the namespace the bridge ended up assigning. Your expectations hold. The two conditions are not interchangeable in general though, bare xmlns carries no lexbor prefix but is namespaced; they only coincide for an attribute named id.
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(). No namespace test is needed at all: lexbor assigns an attribute the xml, xlink or xmlns namespace only through its adjust-foreign-attributes table, and no entry there carries the local name id, so an attribute named id is always unprefixed. Closes phpGH-23598
25a8e7d to
f28a034
Compare
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 set only for the xmlns, xlink and xml namespaces. That guard stays load-bearing because a fragment parsed into a foreign context inherits the context namespace, which the test now pins. Closes phpGH-23598
f28a034 to
3e45b39
Compare
The bridge registered an id as XML_ATTRIBUTE_ID only when lexbor reported the HTML namespace, so ids on SVG and MathML elements never reached getElementById(). Separately, lexbor initializes every attribute node with its element's namespace and overrides that only through the foreign-attribute adjust table, which the parser wires up for SVG and MathML alone, so a fragment parsed with an xlink, xml or xmlns context element came back as <z xlink:id="q" xlink:foo="1">. Restrict the three namespace branches to attributes lexbor adjusted, and key the id registration off the namespace the bridge assigned. Closes phpGH-23598
3e45b39 to
6761e4f
Compare
Two defects in
lexbor_libxml2_bridge_convert(). The id registration tested for lexbor's HTML namespace, soDom\HTMLDocument::getElementById()never found ids on SVG or MathML elements. Separately, the xlink, xml and xmlns branches tested a field that lexbor initializes from the element's namespace and overrides only through the foreign-attribute adjust table, which the parser wires up for SVG and MathML alone, so a fragment parsed with an xlink, xml or xmlns context element came back as<z xlink:id="q" xlink:foo="1">.Restricting those branches to attributes lexbor actually adjusted fixes the second, and leaves
lxml_attr->nsas the right thing for the id check to read.