Обходить дочерние узлы с помощью PHP DOMXpath? - PullRequest
6 голосов
/ 26 октября 2011

У меня проблемы с пониманием того, что именно хранится в childNodes.В идеале я хотел бы сделать еще один xquery для каждого из дочерних узлов, но, похоже, не могу сделать это прямо.Вот мой сценарий: Данные:

<div class="something">
    <h3>
        <a href="link1.html">Link text 1</a>
    </h3>
    <div class"somethingelse">Something else text 1</div>
</div>
<div class="something">
    <h3>
        <a href="link2.html">Link text 2</a>
    </h3>
    <div class"somethingelse">Something else text 2</div>
</div>
<div class="something">
    <h3>
        <a href="link3.html">Link text 3</a>
    </h3>
    <div class"somethingelse">Something else text 3</div>
</div>

И код:

$html = new DOMDocument();
$html->loadHtmlFile($local_file);
$xpath = new DOMXPath( $html );
$nodelist = $xpath->query( "//div[@class='something']");
foreach ($nodelist as $n) {
    Can I run another query here? }

Для каждого элемента «что-то» (т. Е. $ N) я хочу получить доступ к значениям двухкусочки текста и href.Я попытался использовать childNode и другой xquery, но не смог заставить что-либо работать.Любая помощь будет принята с благодарностью!

Ответы [ 4 ]

11 голосов
/ 26 октября 2011

Да, вы можете запустить другой запрос xpath, что-то вроде этого:

foreach ($nodelist as $n)
{
    $other_nodes = $xpath->query('div[@class="somethingelse"]', $n);

    echo $other_nodes->length;
}

Это даст вам внутренний div с классом someelse, второй аргумент метода запроса $ xpath-> указывает запрашивать использование этого узла в качестве контекста, подробнее http://fr2.php.net/manual/en/domxpath.query.php

3 голосов
/ 26 октября 2011

У Трэкса это было, но он пропустил последнее предложение вопроса:

foreach ($nodelist as $n){
    $href = $xpath->query('h3/a', $n)->item(0)->getAttribute('href');
    $a_text = $xpath->query('h3/a', $n)->item(0)->nodeValue;
    $div_text = $xpath->query('div', $n)->item(0)->nodeValue;
}
2 голосов
/ 10 августа 2014

Если я правильно понимаю ваш вопрос, он сработал, когда я использовал выражение потомок ::.Попробуйте это:

foreach ($nodelist as $n) {
    $other_nodes = $xpath->query('descendant::div[@class="some-descendant"]', $n);

    echo $other_nodes->length;
    echo $other_nodes->item(0)->nodeValue;
}

Хотя иногда достаточно просто объединить запросы, используя // выражение пути для сужения поиска.// Выражение пути выбирает узлы в документе, начиная с текущего узла, соответствующего селектору.

$nodes = $xpath->query('//div[@class="some-descendant"]//div[@class="some-descendant-of-that-descendant"]');

Затем выполните цикл по тем элементам, которые вам нужны.Надеюсь, это поможет.

0 голосов
/ 01 марта 2016

Вот фрагмент кода, который позволяет получить доступ к информации, содержащейся в каждом из узлов с атрибутом класса «что-то»:

$nodes_tracker = 0;
$nodes_array = array();
foreach($nodelist as $n){
    $info = $xpath->query('//h3//a', $n)->item($nodes_tracker)->nodeValue;
    $extra_info = $xpath->query('//div[@class="somethingelse"', $n)->item($nodes_tracker)->nodeValue;
    array_push($nodes_array, $info. ' - '. $extra_info . '<br>'); //Add each info to array  
    $nodes_tracker++;
}
print_r($nodes_array);`
...