PHP DOMXPath удаляет мои теги внутри сопоставленного текста - PullRequest
4 голосов
/ 04 апреля 2010

Я задал этот вопрос вчера, и в то время это было именно то, что мне было нужно, но работая с некоторыми живыми данными, я обнаружил, что это не совсем то, что я ожидал. Анализ HTML с HTML-документом PHP DOM

Он получает данные со страницы HTML, но затем он также удаляет все теги HTML внутри захваченного блока текста, что мне не нужно. (Возможно, мне не хотелось бы удалять некоторые теги, но не все, и это можно сделать позже)

Ответы [ 2 ]

8 голосов
/ 04 апреля 2010

Это общая проблема с DOM: вам нужно проделать немного больше работы, если вы хотите получить содержимое тега и содержимое всех его дочерних элементов.

По сути, вам нужно перебрать дочерние узлы того, который вы сопоставили с вашим запросом XPath, чтобы получить их содержимое.

Существует одно решение, предложенное в одном из примечаний пользователя на странице руководства DOMElement класса - см. в этом примечании .


Интеграция этого решения в код, который у вас уже есть, должна дать вам нечто похожее на объявление строки HTML с вложенными тегами:

$html = <<<HTML
<div class="main">
    <div class="text">
        <p>
            Capture this <strong>text</strong> <em>1</em>
        </p>
        <p>
            And some other <strong>text</strong>
        </p>
    </div>
</div>
HTML;


И, чтобы извлечь данные из этой строки HTML, вы можете использовать что-то вроде этого:

$dom = new DOMDocument();
$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$tags = $xpath->query('//div[@class="main"]/div[@class="text"]');
foreach ($tags as $tag) {
    $innerHTML = '';

    // see http://fr.php.net/manual/en/class.domelement.php#86803
    $children = $tag->childNodes;
    foreach ($children as $child) {
        $tmp_doc = new DOMDocument();
        $tmp_doc->appendChild($tmp_doc->importNode($child,true));       
        $innerHTML .= $tmp_doc->saveHTML();
    }

    var_dump(trim($innerHTML));
}

Единственное, что изменилось, это содержимое цикла foreach: вместо простого использования $tag->nodeValue вам придется перебирать дочерние элементы.


Что дает мне следующий вывод:

string '<p>
            Capture this <strong>text</strong> <em>1</em>
        </p>


<p>
            And some other <strong>text</strong>
        </p>' (length=150)

Что является полным содержимым сопоставленного тега <div> и всех его дочерних элементов, включая теги.


Примечание: в примечаниях к руководству пользователя часто встречаются интересные идеи и решения; -)

1 голос
/ 08 мая 2014

Паскаль МАРТИН отвечает отлично, но я обнаружил, что его можно упростить

$dom = new DOMDocument();
$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$tags = $xpath->query('//div[@class="main"]/div[@class="text"]');
foreach ($tags as $tag) {
    $innerHTML = '';

    $children = $tag->childNodes;
    foreach ($children as $child) {     
        $innerHTML .= $dom->saveHTML($child);
    }

    var_dump(trim($innerHTML));
}

Этот способ дает тот же результат, но не требует создания новых DomDocument объектов внутри foreach loop.

РЕДАКТИРОВАТЬ:

Таким образом, после дальнейших экспериментов, вы можете уменьшить приведенное выше значение до:

$dom = new DOMDocument();
$dom->loadHTML($html);

$xpath = new DOMXPath($dom);

$tags = $xpath->query('//div[@class="main"]/div[@class="text"]');
foreach ($tags as $tag) {
    var_dump(trim($dom->saveHTML($tag)));
}
...