Reputation: 13517
How can I query an xpath result for a sub element, without querying the entire document again?
I query my document to find the last <li>
with the class menu-item
:
$doc = new DomDocument();
@$doc->loadHTML( $html );
// $html is invalid (and should be at this point),
// so use @ sign to suppress errors
$xpath = new DomXPath( $doc );
$li = $xpath->query( "(//li[contains(concat(' ', normalize-space(@class), ' '), 'menu-item')])[last()]" )->item( 0 );
The above works just fine, now I want to query $li
to find the following:
$p = $xpath->query( "//p[contains(concat(' ', normalize-space(@class), ' '), 'field-description')]" )->item( 0 );
A p
tag with class field-description
. This does not work and returns the first instance found, if I modify it and use the [last()]
(whatever this is) then it works, but it's not necessarily the optimal solution here:
$p = $xpath->query( "(//p[contains(concat(' ', normalize-space(@class), ' '), 'field-description')])[last()]" )->item( 0 );
The above line works, but I want to query inside $li
not the entire document again.
Upvotes: 3
Views: 2509
Reputation: 77167
The second argument to query
is the contextnode
, which limits the search to within that node. However, if you use an absolute xpath, query
will still return nodes for the entire document.
php > $dd = new DomDocument();
php > // deliberately using malformed html.
php > $dd->loadhtml('<html><head><title>wat</title></head><body><div>Hello, <p>world</p></div><div class="container"><p>I like pie</div></body></html>');
php > $xp = new DomXPath($dd);
php > $container = $xp->query('//div[@class="container"]')->item(0);
php > var_dump($xp->query('//p'));
class DOMNodeList#6 (1) {
public $length =>
int(2)
}
php > var_dump($xp->query('//p', $container));
class DOMNodeList#4 (1) {
public $length =>
int(2)
}
php > var_dump($xp->query('p', $container));
class DOMNodeList#5 (1) {
public $length =>
int(1)
}
You can use a pattern like .//x
to match all x
elements recursively within a context node. (HT: Alf Eaton)
Upvotes: 4