If your expression returns a node set, you will get a DOMNodeList instead of a typed result. Instead, try modifying your expression from "//node[1]" to "string(//node[1])".
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
DOMXPath::evaluate — Evaluates the given XPath expression and returns a typed result if possible
$expression
, ?DOMNode $contextNode
= null
, bool $registerNodeNS
= true
): mixed
Executes the given XPath expression
and returns
a typed result if possible.
expression
The XPath expression to execute.
contextNode
The optional contextNode
can be specified for
doing relative XPath queries. By default, the queries are relative to
the root element.
registerNodeNS
Legt fest, ob die Namensraum-Präfixe innerhalb des Geltungsbereichs des Kontextknotens automatisch im DOMXPath-Objekt registriert werden sollen. Dies kann verwendet werden, damit DOMXPath::registerNamespace() nicht manuell für jeden Namensraum innerhalb des Geltungsbereichs aufgerufen werden muss. Wenn es einen Konflikt zwischen Namensraum-Präfixen gibt, wird nur das in der Reihenfolge nächste Namensraum-Präfix registriert.
Returns a typed result if possible or a DOMNodeList
containing all nodes matching the given XPath expression
.
If the expression
is malformed or the
contextNode
is invalid,
DOMXPath::evaluate() returns false
.
Beispiel #1 Getting the count of all the english books
<?php
$doc = new DOMDocument;
$doc->load('book.xml');
$xpath = new DOMXPath($doc);
$tbody = $doc->getElementsByTagName('tbody')->item(0);
// our query is relative to the tbody node
$query = 'count(row/entry[. = "en"])';
$entries = $xpath->evaluate($query, $tbody);
echo "There are $entries english books\n";
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
There are 2 english books
If your expression returns a node set, you will get a DOMNodeList instead of a typed result. Instead, try modifying your expression from "//node[1]" to "string(//node[1])".
Note that this method does not provide any means to distinguish between a successful result that returns FALSE and an error.
For example, this will succeed and return FALSE:
<?php $xpath->evaluate("1 = 0"); ?>
One workaround when you know you are expecting a Boolean is to wrap the result with string(). e.g.
<?php $xpath->evaluate("string(1 = 0)"); ?>
This will return a string "false" on success, or the Boolean FALSE on error.
this class can substitute the method evaluate while it is not validated. Made for Yuri Bastos and Jo�o Gilberto Magalh�es.
<?php
class XPtahQuery
{
// function returns a DOMNodeList from a relative xPath
public static function selectNodes($pNode, $xPath)
{
$pos = strpos(self::getFullXpath($pNode),"/",1);
$xPathQuery = substr(self::getFullXpath($pNode),$pos);//to paste /#document[1]/
$xPathQueryFull = $xPathQuery. $xPath;
$domXPath = new DOMXPath($pNode->ownerDocument);
$rNodeList = $domXPath->query($xPathQueryFull);
return $rNodeList;
}
// function returns a DOMNode from a xPath from other DOMNode
public static function selectSingleNode($pNode, $xPath)
{
$pos = strpos(self::getFullXpath($pNode),"/",1);
$xPathQuery = substr(self::getFullXpath($pNode),$pos);//to paste /#document[1]/
$xPathQueryFull = $xPathQuery. $xPath;
$domXPath = new DOMXPath($pNode->ownerDocument);
$rNode = $domXPath->query($xPathQueryFull)->item(0);
return $rNode;
}
//utilitaries functions off selectSingleNode
private function getNodePos($pNode, $nodeName)
{
if($pNode == null)
{
return 0;
}
else
{
$var = 0;
if ($pNode->previousSibling != null)
{
if ($pNode->previousSibling->nodeName == $nodeName)
{
$var = 1;
}
}
return self::getNodePos($pNode->previousSibling, $nodeName) + $var;
}
}
//utilitaries functions off selectSingleNode
private function getFullXpath($pNode)
{
if($pNode == null)
{
return "";
}
else
{
return self::getFullXpath($pNode->parentNode) . "/" . $pNode->nodeName . "[" .strval(self::getNodePos($pNode, $pNode->nodeName)+1) . "]";//+1 to get the real xPath index
}
}
}
?>
To query DOMNodes by their HTML classes, use such snippet
<?php
// CssClassXPathSelector
function ccxs($class) {
return '[contains(concat(" ", normalize-space(@class), " "), " ' . $class . ' ")]';
}
// then just
$domitems = $this->xpath("//*[@id='searchResultsRows']//a" . ccxs('listing_row'));
?>
The only way how to distinguish FALSE returned value from syntax error FALSE is to re-run the XPath expression wrapped in string() function. If must return empty string. If it returns FALSE again then it is an error.
<?php
$ret=$this->xp->evaluate($eval, $context);
// Error detection: DOMXPath::evaluate() returns FALSE on error
// so does DOMXPath::evaluate("boolean(/nothing)")
// @workaround webdevelopers.eu
if ($ret === false && $this->xp->evaluate("string($eval)", $context) === false) {
throw new Exception("Invalid XPath expression ".json_encode($eval), 3491);
}
?>