У меня есть строка html, содержащая в ней ровно один a-элемент. Пример:
<a href="http://www.test.com" rel="nofollow external">test</a>
В php мне нужно проверить, содержит ли rel внешние и если да, то измените href и сохраните строку.
Я искал узлы и объекты DOM. Но они кажутся слишком сильными только для одного элемента A, поскольку я должен итерации, чтобы получить html-узлы, и я не уверен, как проверить, существует ли rel и содержит внешние .
$html = new DOMDocument(); $html->loadHtml($txt); $a = $html->getElementsByTagName('a'); $attr = $a->item(0)->attributes(); ...
На этом этапе я собираюсь получить NodeMapList, который кажется накладным. Есть ли более простой способ для этого или я должен делать это с DOM?
Есть ли более простой способ для этого или я должен делать это с DOM?
Сделайте это с помощью DOM.
Вот пример:
<?php $html = '<a href="http://example.com" rel="nofollow external">test</a>'; $dom = new DOMDocument; $dom->loadHTML($html); $xpath = new DOMXPath($dom); $nodes = $xpath->query("//a[contains(concat(' ', normalize-space(@rel), ' '), ' external ')]"); foreach($nodes as $node) { $node->setAttribute('href', 'http://example.org'); } echo $dom->saveHTML();
Лучший способ – использовать парсер HTML / DOM, но это решение регулярных выражений:
$html = '<a href="http://www.test.com" rel="nofollow external">test</a><br> <p> Some text</p> <a href="http://test.com">test2</a><br> <a rel="external">test3</a> <-- This won\'t work since there is no href in it. '; $new = preg_replace_callback('/<a.+?rel\s*=\s*"([^"]*)"[^>]*>/i', function($m){ if(strpos($m[1], 'external') !== false){ $m[0] = preg_replace('/href\s*=\s*(("[^"]*")|(\'[^\']*\'))/i', 'href="http://example.com"', $m[0]); } return $m[0]; }, $html); echo $new;
Онлайн-демонстрация .
Я продолжал изменять с помощью DOM. Это то, что я получаю:
$html = new DOMDocument(); $html->loadHtml('<?xml encoding="utf-8" ?>' . $txt); $nodes = $html->getElementsByTagName('a'); foreach ($nodes as $node) { foreach ($node->attributes as $att) { if ($att->name == 'rel') { if (strpos($att->value, 'external')) { $node->setAttribute('href','modified_url_goes_here'); } } } } $txt = $html->saveHTML();
Я не хотел загружать любую другую библиотеку только для одной строки.
Вы можете использовать регулярное выражение, например, if it matches /\s+rel\s*=\s*".*external.*"/
затем замените /(<a.*href\s*=\s*")([^"]\)("[^>]*>)/\1[your new href here]\3/
как /(<a.*href\s*=\s*")([^"]\)("[^>]*>)/\1[your new href here]\3/
Хотя использование библиотеки, которая может делать такие вещи для вас, намного проще (например, jquery для javascript)