Как выполнить запрос XPath на DOMNode? - программирование
Подтвердить что ты не робот

Как выполнить запрос XPath на DOMNode?

Есть ли способ сделать запрос 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
}
4b9b3361

Ответ 1

Передайте node в качестве второго аргумента 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 всех атрибутов с атрибутом класса для перечисления и вывода комбинированных значений текста node, включая пробелы

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

Ответ 2

Укажите $node как контекст node.

foreach ($nodes as $node)
{
   $morenodes = $x_path->query(".//h3", $node);
}

См. $contextnode в руководстве: http://php.net/manual/en/domxpath.query.php

Ответ 3

Чтобы завершить его, существует метод DOMNode::getNodePath, который возвращает xpath этого node. Таким образом, вы также можете использовать $x_path->query($node->getNodePath().'//h3')