php — простой HTML-дом — элементы между другими элементами

Я пытаюсь написать php-скрипт для обхода веб-сайта и сохранения некоторых элементов в базе данных.

Вот моя проблема: веб-страница написана так:

<h2>The title 1</h2>
<p class="one_class"> Some text </p>
<p> Some interesting text </p>

<h2>The title 2</h2>
<p class="one_class"> Some text </p>
<p> Some interesting text </p>

<p class="one_class"> Some different text </p>
<p> Some other interesting text </p>

<h2>The title 3</h2>
<p class="one_class"> Some text </p>
<p> Some interesting text </p>

Я хочу получить только h2 и p с интересным текстом, а не p class="one_class".

Я попробовал этот php-код:

<?php
$numberP = 0;
foreach($html->find('p') as $p)
{
    $pIsOneClass = PIsOneClass($html, $p);

    if($pIsOneClass == false)
    {   
        echo $p->outertext;
                $h2 = $html->find("h2", $numberP);
                echo $h2->outertext;
                $numberP++;  
        }

}
?>

функция PIsOneClass($html, $p):

<?php
function PIsOneClass($html, $p) 
{
foreach($html->find("p.one_class") as $p_one_class)
    {
        if($p ==  $p_one_class)
        {
            return true;
        }           
    }
    return false;
}
?> 

Это не работает, я понимаю почему, но я не знаю, как это решить.

Как мы можем сказать: «Мне нужны все p без класса, находящиеся между двумя h2?»

Большое спасибо !


person Maxime Thizeau    schedule 19.10.2014    source источник
comment
Если они все p.one_class, почему бы не найти эти теги p и не удалить их перед выводом результата для сохранения?   -  person Jared Farrish    schedule 19.10.2014
comment
Но как я могу заказать h2 и p ? С помощью этого скрипта он печатает h2 p h2 p h2 p, но я хочу что-то вроде h2 p p h2 p   -  person Maxime Thizeau    schedule 19.10.2014


Ответы (2)


Эта задача упрощается с XPath, поскольку вы очищаете более одного элемента и хотите поддерживать порядок в исходном коде. Вы можете использовать библиотеку PHP DOM, которая включает DOMXPath, для поиска и фильтрации нужных элементов:

$html = '<h2>The title 1</h2>
<p class="one_class"> Some text </p>
<p> Some interesting text </p>

<h2>The title 2</h2>
<p class="one_class"> Some text </p>
<p> Some interesting text </p>

<p class="one_class"> Some different text </p>
<p> Some other interesting text </p>

<h2>The title 3</h2>
<p class="one_class"> Some text </p>
<p> Some interesting text </p>';

# create a new DOM document and load the html
$dom = new DOMDocument;
$dom->loadHTML($html);
# create a new DOMXPath object
$xp = new DOMXPath($dom);

# search for all h2 elements and all p elements that do not have the class 'one_class'
$interest = $xp->query('//h2 | //p[not(@class="one_class")]');

# iterate through the array of search results (h2 and p elements), printing out node
# names and values
foreach ($interest as $i) {
    echo "node " . $i->nodeName . ", value: " . $i->nodeValue . PHP_EOL;
}

Выход:

node h2, value: The title 1
node p, value:  Some interesting text 
node h2, value: The title 2
node p, value:  Some interesting text 
node p, value:  Some other interesting text 
node h2, value: The title 3
node p, value:  Some interesting text 

Как видите, исходный текст остается в порядке, и можно легко удалить ненужные узлы.

person i alarmed alien    schedule 19.10.2014
comment
Спасибо, я не знал, что существует. Можно ли одновременно использовать Simple Html Dom или это бесполезно? - person Maxime Thizeau; 19.10.2014
comment
Вы не можете выполнять операции XPath с простой HTML DOM, но вы можете вывести HTML из DOMDocument, а затем прочитать его с помощью SHD. Однако вы должны иметь возможность делать с DOM все, что хотите, — это очень обширная библиотека для работы с XML. Вот руководство. - person i alarmed alien; 20.10.2014

Из руководства по простому HTML dom.

[attribute=value]   

Сопоставляет элементы, имеющие указанный атрибут, с определенным значением. или

[!attribute]

Соответствует элементам, не имеющим указанного атрибута.

person Billy    schedule 19.10.2014