mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02: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
3 changed files with 90 additions and 1 deletions
2
NEWS
2
NEWS
|
@ -11,6 +11,8 @@ PHP NEWS
|
||||||
. Fixed bug GH-10234 (Setting DOMAttr::textContent results in an empty
|
. Fixed bug GH-10234 (Setting DOMAttr::textContent results in an empty
|
||||||
attribute value). (nielsdos)
|
attribute value). (nielsdos)
|
||||||
. Fix return value in stub file for DOMNodeList::item. (divinity76)
|
. Fix return value in stub file for DOMNodeList::item. (divinity76)
|
||||||
|
. Fix spec compliance error with '*' namespace for
|
||||||
|
DOMDocument::getElementsByTagNameNS. (nielsdos)
|
||||||
|
|
||||||
- Opcache:
|
- Opcache:
|
||||||
. Fix allocation loop in zend_shared_alloc_startup(). (nielsdos)
|
. 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;
|
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)) {
|
while (nodep != NULL && (*cur <= index || index == -1)) {
|
||||||
if (nodep->type == XML_ELEMENT_NODE) {
|
if (nodep->type == XML_ELEMENT_NODE) {
|
||||||
if (xmlStrEqual(nodep->name, (xmlChar *)local) || xmlStrEqual((xmlChar *)"*", (xmlChar *)local)) {
|
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) {
|
if (*cur == index) {
|
||||||
ret = nodep;
|
ret = nodep;
|
||||||
break;
|
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…
Add table
Add a link
Reference in a new issue