Есть ли способ сделать запрос xpath на DOMNode? Или, по крайней мере, преобразовать его в DOMXPath?
<html> ... <div id="content"> ... <div class="listing"> ... <div></div> <div></div> <div class='foo'> <h3>Get me 1</h3> <a>and me too 1</a> </div> </div> <div class="listing"> ... <div></div> <div></div> <div class='foo'> <h3>Get me 2</h3> <a>and me too 1</a> </div> </div> .... </div> </html>
Это мой код. Я пытаюсь получить список массива, который имеет значения h3 и теги в каждом массиве. Для этого мне нужно было получить каждый список, а затем получить значение h3 и значение тега в каждом листинге.
$html_dom = new DOMDocument(); @$html_dom->loadHTML($html); $x_path = new DOMXPath($html_dom); $nodes= $x_path->query("//div[@id='content']//div[@class='listing']"); foreach ($nodes as $node) { // I want to further dig down here using query on a DOMNode }
Передайте узел в качестве второго аргумента в DOMXPath::query
contextnode : необязательный contextnode может быть указан для выполнения относительных запросов XPath. По умолчанию запросы относятся к корневому элементу.
Пример:
foreach ($nodes as $node) { foreach ($x_path->query('h3|a', $node) as $child) { echo $child->nodeValue, PHP_EOL; } }
Это использует оператор UNION для результата
Get me 1 and me too 1 Get me 2 and me too 1
Если вам не нужны сложные запросы, вы также можете сделать
foreach ($nodes as $node) { foreach ($node->getElementsByTagName('a') as $a) { echo $a->nodeValue, PHP_EOL; } }
Или даже путем итерации дочерних узлов (обратите внимание, что это включает в себя все текстовые узлы)
foreach ($nodes as $node) { foreach ($node->childNodes as $child) { echo $child->nodeName, PHP_EOL; } }
Однако все это не требуется, поскольку вы можете напрямую получить эти узлы:
$nodes= $x_path->query("/html/body//div[@class='listing']/div[last()]"); foreach ($nodes as $i => $node) { echo $i, $node->nodeValue, PHP_EOL; }
даст вам два узла в последнем дочернем div всех div с атрибутом класса для перечисления и вывода значений комбинированного текстового узла, включая пробелы
0 Get me 1 and me too 1 1 Get me 2 and me too 1
Аналогичным образом, следующее
"//div[@class='listing']/div[last()]/node()[name() = 'h3' or name() = 'a']"
даст вам четыре дочерних узла H3 и A и выход
0Get me 1 1and me too 1 2Get me 2 3and me too 1
Если вам нужно различать их по имени, итерации по ним, вы можете сделать
foreach ($nodes as $i => $node) { echo $i, $node->nodeName, $node->nodeValue, PHP_EOL; }
который затем даст
0h3Get me 1 1aand me too 1 2h3Get me 2 3aand me too 1
Предоставьте свой $node
в качестве контекстного узла.
foreach ($nodes as $node) { $morenodes = $x_path->query(".//h3", $node); }
См. $contextnode
в руководстве: http://php.net/manual/en/domxpath.query.php
Чтобы завершить его, существует метод DOMNode::getNodePath
который возвращает xpath этого узла. Таким образом, вы также можете использовать $x_path->query($node->getNodePath().'//h3')