PHP - DOMDocument - удалить теги вокруг текста на основе класса - PullRequest
1 голос
/ 12 февраля 2011

У меня есть HTML-документ, из которого я хочу удалить определенные теги, определенные конкретным классом.Теги имеют несколько классов.Очень простой пример разметки, который у меня есть:

<style>.c{background-color:yellow}</style>
This is a <span class="a b c">string</span>.  
This is <span class="a b c">another string</span>.  
This is <span class="a b">yet another string</span>.

Я хочу иметь возможность анализировать эту строку (желательно с использованием PHP DOMDocument?), Находя только теги <span> с классом cрезультат будет выглядеть примерно так:

<style>.c{background-color:yellow}</style>
This is a string.  
This is another string.  
This is <span class="a b">yet another string</span>.

По сути, я хочу удалить теги вокруг текста, но сохранить текст в документе.

Обновление: я думаюЯ близко, но у меня это не работает:

$test = '<style>.c {background-color:yellow;}</style>' .
'This is a <span class="a b c">string</span>.'.
'This is <span class="a b c">another string</span>.' .
'This is <span class="a b">yet another string</span>.';

$doc = new DOMDocument();
$doc->loadHTML($test);
$xpath = new DOMXPath($doc);
$query = "//span[contains(@class, 'c')]"; // thanks to Gordon
$oldnodes = $xpath->query($query);

foreach ($oldnodes as $oldnode) {
    $txt = $oldnode->nodeValue;
    $oldnode->parentNode->replaceChild($txt, $oldnode);
}

echo $doc->saveHTML();

1 Ответ

2 голосов
/ 12 февраля 2011

Вы близки ... Создайте фрагмент для детей:

$query = "//span[contains(concat(' ', normalize-space(@class), ' '), ' c ')]";
$oldnodes = $xpath->query($query);

foreach ($oldnodes as $node) {
    $fragment = $doc->createDocumentFragment();
    while($node->childNodes->length > 0) {
        $fragment->appendChild($node->childNodes->item(0));
    }
    $node->parentNode->replaceChild($fragment, $node);
}

Так как каждая итерация удалит $node, нет необходимости повторять (она будет динамически удалять ее изрезультирующий набор, так как он больше не действителен) ...

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

<span class="a b c">foo <b>bar</b> baz</span>

Обратите внимание на недавнее редактирование: я изменилзапрос xpath будет более устойчивым, поскольку теперь он будет соответствовать только точным классам c, а не toc ...

Что странно, так это то, что он позволяет удалять в итерации, не влияя на результаты (язнаю, что это было сделано раньше, я просто не знаю, почему здесь).Но это проверенный код, и он должен быть хорошим.

...