Использование регулярных выражений для удаления тегов HTML - PullRequest
3 голосов
/ 05 мая 2010

Мне нужно преобразовать

$text = 'We had <i>fun</i>. Look at <a href="http://example.com">this photo</a> of Joe';

[Изменить] В тексте может быть несколько ссылок.

в

$text = 'We had fun. Look at this photo (http://example.com) of Joe';

Все теги HTML должны быть удалены, а значение href из тегов <a> должно быть добавлено, как указано выше.

Какой эффективный способ решить эту проблему с помощью регулярных выражений?Подойдет любой фрагмент кода.

Ответы [ 5 ]

5 голосов
/ 05 мая 2010

Сначала сделайте preg_replace, чтобы сохранить ссылку.Вы можете использовать:

preg_replace('<a href="(.*?)">(.*?)</a>', '$\2 ($\1)', $str);

Затем используйте strip_tags, который завершит остальные теги.

1 голос
/ 05 мая 2010

Решение DOM:

$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
foreach($xpath->query('//a[@href]') as $node) {
    $textNode = new DOMText(sprintf('%s (%s)',
        $node->nodeValue, $node->getAttribute('href')));
    $node->parentNode->replaceChild($textNode, $node);
}
echo strip_tags($dom->saveHTML());

и то же без XPath:

$dom = new DOMDocument;
$dom->loadHTML($html);
foreach($dom->getElementsByTagName('a') as $node) {
    if($node->hasAttribute('href')) {
        $textNode = new DOMText(sprintf('%s (%s)',
            $node->nodeValue, $node->getAttribute('href')));
        $node->parentNode->replaceChild($textNode, $node);
    }
}
echo strip_tags($dom->saveHTML());

Все, что он делает, это загружает любой HTML в экземпляр DomDocument. В первом случае он использует выражение XPath, которое похоже на SQL для XML, и получает все ссылки с атрибутом href. Затем он создает элемент текстового узла из innerHTML и атрибута href и заменяет ссылку. Вторая версия просто использует DOM API и не использует Xpath.

Да, это на несколько строк больше, чем в Regex, но это чисто и легко понять, и это не доставит вам головной боли, когда вам потребуется добавить дополнительную логику.

1 голос
/ 05 мая 2010

попробуйте синтаксический анализатор xml, чтобы заменить любой тег своим внутренним html, а теги a - атрибутом href.

http://www.php.net/manual/en/book.domxml.php

0 голосов
/ 05 мая 2010

Это также очень легко сделать с помощью парсера:

# available from http://simplehtmldom.sourceforge.net
include('simple_html_dom.php');

# parse and echo
$html = str_get_html('We had <i>fun</i>. Look at <a href="http://example.com">this photo</a> of Joe');

$a = $html->find('a');
$a[0]->outertext = "{$a[0]->innertext} ( {$a[0]->href} )";

echo strip_tags($html);

И он производит код, который вы хотите в своем тестовом примере.

0 голосов
/ 05 мая 2010

Я делал такие вещи, используя вариации подстроки и замены. Я бы, наверное, сегодня использовал регулярное выражение , но вы хотели альтернативу так:

Для тегов <i> я бы сделал что-то вроде:

$text = replace($text, "<i>", "");
$text = replace($text, "</i>", "");

(Мой php действительно ржавый, поэтому replace может быть неправильным названием функции - но идея в том, что я делюсь.)

Тег <a> немного сложнее. Но это может быть сделано. Вам нужно найти точку, с которой начинается <a и с которой заканчивается >. Затем вы извлекаете всю длину и заменяете закрывающую </a>

Это может пойти что-то как:

$start = strrpos( $text, "<a" );
$end = strrpos( $text, "</a>", $start );
$text = substr( $text,  $start, $end );
$text = replace($text, "</a>", "");

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

Справка:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...