mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Fix spec compliance error for DOMDocument::getElementsByTagNameNS
Spec link: https://dom.spec.whatwg.org/#concept-getelementsbytagnamens Spec says we should match any namespace when '*' is provided. This was however not the case: elements that didn't have a namespace were not returned. This patch fixes the error by modifying the namespace check. Closes GH-11343.
This commit is contained in:
parent
9c59d22a7b
commit
154c251013
2
NEWS
2
NEWS
@ -11,6 +11,8 @@ PHP NEWS
|
||||
. Fixed bug GH-10234 (Setting DOMAttr::textContent results in an empty
|
||||
attribute value). (nielsdos)
|
||||
. Fix return value in stub file for DOMNodeList::item. (divinity76)
|
||||
. Fix spec compliance error with '*' namespace for
|
||||
DOMDocument::getElementsByTagNameNS. (nielsdos)
|
||||
|
||||
- Opcache:
|
||||
. Fix allocation loop in zend_shared_alloc_startup(). (nielsdos)
|
||||
|
@ -1270,10 +1270,15 @@ xmlNode *dom_get_elements_by_tag_name_ns_raw(xmlNodePtr nodep, char *ns, char *l
|
||||
{
|
||||
xmlNodePtr ret = NULL;
|
||||
|
||||
/* Note: The spec says that ns == '' must be transformed to ns == NULL. In other words, they are equivalent.
|
||||
* PHP however does not do this and internally uses the empty string everywhere when the user provides ns == NULL.
|
||||
* This is because for PHP ns == NULL has another meaning: "match every namespace" instead of "match the empty namespace". */
|
||||
bool ns_match_any = ns == NULL || (ns[0] == '*' && ns[1] == '\0');
|
||||
|
||||
while (nodep != NULL && (*cur <= index || index == -1)) {
|
||||
if (nodep->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrEqual(nodep->name, (xmlChar *)local) || xmlStrEqual((xmlChar *)"*", (xmlChar *)local)) {
|
||||
if (ns == NULL || (!strcmp(ns, "") && nodep->ns == NULL) || (nodep->ns != NULL && (xmlStrEqual(nodep->ns->href, (xmlChar *)ns) || xmlStrEqual((xmlChar *)"*", (xmlChar *)ns)))) {
|
||||
if (ns_match_any || (!strcmp(ns, "") && nodep->ns == NULL) || (nodep->ns != NULL && xmlStrEqual(nodep->ns->href, (xmlChar *)ns))) {
|
||||
if (*cur == index) {
|
||||
ret = nodep;
|
||||
break;
|
||||
|
@ -0,0 +1,82 @@
|
||||
--TEST--
|
||||
DOMDocument::getElementsByTagNameNS() match any namespace
|
||||
--EXTENSIONS--
|
||||
dom
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/* Sample document taken from https://www.php.net/manual/en/domdocument.getelementsbytagname.php */
|
||||
$xml = <<<EOD
|
||||
<?xml version="1.0" ?>
|
||||
<chapter xmlns:xi="http://www.w3.org/2001/XInclude">
|
||||
<title>Books of the other guy..</title>
|
||||
<para>
|
||||
<xi:include href="book.xml">
|
||||
<xi:fallback>
|
||||
<error>xinclude: book.xml not found</error>
|
||||
</xi:fallback>
|
||||
</xi:include>
|
||||
<include>
|
||||
This is another namespace
|
||||
</include>
|
||||
</para>
|
||||
</chapter>
|
||||
EOD;
|
||||
$dom = new DOMDocument;
|
||||
|
||||
// load the XML string defined above
|
||||
$dom->loadXML($xml);
|
||||
|
||||
function test($namespace, $local) {
|
||||
global $dom;
|
||||
$namespace_str = $namespace !== NULL ? "'$namespace'" : "null";
|
||||
echo "-- getElementsByTagNameNS($namespace_str, '$local') --\n";
|
||||
foreach ($dom->getElementsByTagNameNS($namespace, $local) as $element) {
|
||||
echo 'local name: \'', $element->localName, '\', prefix: \'', $element->prefix, "'\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Should *also* include objects even without a namespace
|
||||
test(null, '*');
|
||||
// Should *also* include objects even without a namespace
|
||||
test('*', '*');
|
||||
// Should *only* include objects without a namespace
|
||||
test('', '*');
|
||||
// Should *only* include objects with the specified namespace
|
||||
test('http://www.w3.org/2001/XInclude', '*');
|
||||
// Should not give any output
|
||||
test('', 'fallback');
|
||||
// Should not give any output, because the null namespace is the same as the empty namespace
|
||||
test(null, 'fallback');
|
||||
// Should only output the include from the empty namespace
|
||||
test(null, 'include');
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
-- getElementsByTagNameNS(null, '*') --
|
||||
local name: 'chapter', prefix: ''
|
||||
local name: 'title', prefix: ''
|
||||
local name: 'para', prefix: ''
|
||||
local name: 'error', prefix: ''
|
||||
local name: 'include', prefix: ''
|
||||
-- getElementsByTagNameNS('*', '*') --
|
||||
local name: 'chapter', prefix: ''
|
||||
local name: 'title', prefix: ''
|
||||
local name: 'para', prefix: ''
|
||||
local name: 'include', prefix: 'xi'
|
||||
local name: 'fallback', prefix: 'xi'
|
||||
local name: 'error', prefix: ''
|
||||
local name: 'include', prefix: ''
|
||||
-- getElementsByTagNameNS('', '*') --
|
||||
local name: 'chapter', prefix: ''
|
||||
local name: 'title', prefix: ''
|
||||
local name: 'para', prefix: ''
|
||||
local name: 'error', prefix: ''
|
||||
local name: 'include', prefix: ''
|
||||
-- getElementsByTagNameNS('http://www.w3.org/2001/XInclude', '*') --
|
||||
local name: 'include', prefix: 'xi'
|
||||
local name: 'fallback', prefix: 'xi'
|
||||
-- getElementsByTagNameNS('', 'fallback') --
|
||||
-- getElementsByTagNameNS(null, 'fallback') --
|
||||
-- getElementsByTagNameNS(null, 'include') --
|
||||
local name: 'include', prefix: ''
|
Loading…
Reference in New Issue
Block a user