Skip to content

QPXML::pi($prefix) always returns NULL and warns — it reads tagName on a DOMProcessingInstruction #79

Description

@jakejackson1

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions