Guidelines
Description of the bug
The QPXML extension's pi() getter cannot retrieve a processing instruction by prefix. It emits a PHP warning and returns NULL, whatever the document contains. The no-argument form (pi(), "return the first PI") works.
Warning: Undefined property: DOMProcessingInstruction::$tagName in src/Extension/QPXML.php on line 146
Root cause
src/Extension/QPXML.php:132-155 filters on tagName, which DOMProcessingInstruction does not have — the PI name is exposed as target:
foreach ($ele->childNodes as $node) {
if ($node->nodeType == XML_PI_NODE) {
if (isset($prefix)) {
if ($node->tagName == $prefix) { // <-- DOMProcessingInstruction has no tagName
return $node->textContent;
}
} else {
// Return first match.
return $node->textContent;
}
}
}
Under PHP 8 the undefined property read yields NULL plus a warning, so the comparison never succeeds and the method falls through to an implicit NULL return.
Suggested fix
if ($node->target === $prefix) {
The setter half of pi() is fine — it uses createProcessingInstruction($prefix, $text) correctly, so a PI written by QueryPath simply cannot be read back by the same prefix.
Two smaller things in the same method, if it is being touched anyway: it has no DocBlock beyond a one-line summary, and both loops fall off the end without an explicit return null.
QueryPath version
4.2.0 (also reproduces on main at bed5d2c)
PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)
PHP 8.3.16 CLI (macOS, Homebrew). Not PHP-8 specific — the cause is present on every supported version.
Minimal reproducible PHP+HTML snippet to replicate bug
<?php
require __DIR__ . '/vendor/autoload.php';
use QueryPath\QueryPath;
QueryPath::enable(\QueryPath\Extension\QPXML::class);
$qp = qp('<?xml version="1.0"?><root><a/></root>', 'a')->pi('php', 'echo $x;');
var_dump($qp->top()->find('a')->pi('php')); // NULL + warning
var_dump($qp->top()->find('a')->pi()); // 'echo $x;' - works without a prefix
Guidelines
Description of the bug
The
QPXMLextension'spi()getter cannot retrieve a processing instruction by prefix. It emits a PHP warning and returnsNULL, whatever the document contains. The no-argument form (pi(), "return the first PI") works.Root cause
src/Extension/QPXML.php:132-155filters ontagName, whichDOMProcessingInstructiondoes not have — the PI name is exposed astarget:Under PHP 8 the undefined property read yields
NULLplus a warning, so the comparison never succeeds and the method falls through to an implicitNULLreturn.Suggested fix
The setter half of
pi()is fine — it usescreateProcessingInstruction($prefix, $text)correctly, so a PI written by QueryPath simply cannot be read back by the same prefix.Two smaller things in the same method, if it is being touched anyway: it has no DocBlock beyond a one-line summary, and both loops fall off the end without an explicit
return null.QueryPath version
4.2.0 (also reproduces on
mainat bed5d2c)PHP Version and environment (server type, cli provider etc., enclosing libraries and their respective versions)
PHP 8.3.16 CLI (macOS, Homebrew). Not PHP-8 specific — the cause is present on every supported version.
Minimal reproducible PHP+HTML snippet to replicate bug