Изменить атрибут html с помощью php

у меня есть строка 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?

4 ответов


есть ли более простой способ для этого или я должен сделать это с 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, но вот решение regex:

$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.*"/ затем сделайте регулярное выражение replace like /(<a.*href\s*=\s*")([^"]\)("[^>]*>)/[your new href here]/

хотя использование библиотеки, которая может делать такие вещи для вас, намного проще (например, jquery для javascript)