как перечислить элементы с помощью preg_replace? - PullRequest
0 голосов
/ 01 декабря 2010

Мне нужно добавить несколько тегов до и после изображений в документе и сразу их нумеровать. HTML-код документа:

....

<img src="http://img.example.com/img/mage1.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/image72.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/imagstr.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/image.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/imgger.gif" alt="sometile"> <br> 
<img src="http://img.example.com/img/somepic.png" alt="sometile"> <br> 

Мне нужен такой код результата

<div><a name="#pic1"></a><img src="http://img.example.com/img/mage1.jpg" alt="sometile"></div>
<div><a name="#pic2"></a><img src="http://img.example.com/img/image72.jpg" alt="sometile"> </div> 
<div><a name="#pic3"></a><img src="http://img.example.com/img/imagstr.jpg" alt="sometile"> </div> 
<div><a name="#pic4"></a><img src="http://img.example.com/img/image.jpg" alt="sometile"> </div> 
<div><a name="#pic5"></a><img src="http://img.example.com/img/imgger.gif" alt="sometile"> </div> 
<div><a name="#pic6"></a><img src="http://img.example.com/img/somepic.png" alt="sometile"> </div> 

Ответы [ 3 ]

1 голос
/ 01 декабря 2010

Как обычно, вы также можете сделать это с DOM :

$counter = 0;
$doc = new DOMDocument();
$doc->loadHTML($str);
foreach ($doc->getElementsByTagName("img") as $img) {
    $sibling = $img->nextSibling;
    while ($sibling) {
        if ($sibling instanceof DOMElement && $sibling->tagName === 'br') {
            $sibling->parentNode->removeChild($sibling);
        }
        $sibling = $sibling->nextSibling;
    }
    $div = $doc->createElement("div");
    $img->parentNode->replaceChild($div, $img);
    $a = $doc->createElement("a");
    $a->setAttribute("name", "pic" . (++$counter));
    $a->appendChild($img);
    $div->appendChild($a);
}
$str = '';
foreach (simplexml_import_dom($doc->getElementsByTagName("body")->item(0))->children() as $elem) {
    $str .= $elem->asXML();
}
0 голосов
/ 01 декабря 2010

Прежде всего, вы не должны использовать регулярные выражения для работы с HTML.

Однако в этом случае это просто, поскольку вы почти имеете дело с полными строками:

$code = '<img src="http://img.example.com/img/mage1.jpg" alt="sometile"> <br>
<img src="http://img.example.com/img/image72.jpg" alt="sometile"> <br>
<img src="http://img.example.com/img/imagstr.jpg" alt="sometile"> <br>
<img src="http://img.example.com/img/image.jpg" alt="sometile"> <br>
<img src="http://img.example.com/img/imgger.gif" alt="sometile"> <br>
<img src="http://img.example.com/img/somepic.png" alt="sometile"> <br>';

function get_num_row($matches) {
    global $last_num;
    return '<div><a name="pic' . (++$last_num) . '">' . trim($matches[1]) . '</a></div>';
}

$last_num = 0;
$code = preg_replace_callback('/^(.*)<br>$/m', 'get_num_row', $code);
echo $code;

Выход:

<div><a name="pic1"><img src="http://img.example.com/img/mage1.jpg" alt="sometile"></a></div>
<div><a name="pic2"><img src="http://img.example.com/img/image72.jpg" alt="sometile"></a></div>
<div><a name="pic3"><img src="http://img.example.com/img/imagstr.jpg" alt="sometile"></a></div>
<div><a name="pic4"><img src="http://img.example.com/img/image.jpg" alt="sometile"></a></div>
<div><a name="pic5"><img src="http://img.example.com/img/imgger.gif" alt="sometile"></a></div>
<div><a name="pic6"><img src="http://img.example.com/img/somepic.png" alt="sometile"></a></div>

Конечно, вам нужно установить $last_num на 0, если вы собираетесь снова использовать обратный вызов. Нет способа сделать это без глобального или статического var. Но если вы собираетесь использовать обратный вызов только один раз, вы можете просто изменить global $last_num; на static $last_num = 0;. Тогда он будет увеличиваться вечно без возможности его сброса, но он не загромождает ваше глобальное пространство имен.

0 голосов
/ 01 декабря 2010

Я не фанат регулярных выражений + HTML, но здесь идет речь (я только что приготовил простое регулярное выражение & mdash; у вас, вероятно, уже есть):

$s = '<img src="http://img.example.com/img/mage1.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/image72.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/imagstr.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/image.jpg" alt="sometile"> <br> 
<img src="http://img.example.com/img/imgger.gif" alt="sometile"> <br> 
<img src="http://img.example.com/img/somepic.png" alt="sometile"> <br>';

$i = 0;
function wrap($s) {
        global $i;
        $i++;
        return sprintf('<div><a name="pic%d">%s</div>', $i, $s);
}

print preg_replace('#(<img [^>]+?>) <br>#e', "wrap('\\1')", $s);

( Демо )

Важной частью является модификатор e в preg_replace(). Смотрите " Пример # 4 Использование модификатора 'e' ."


EDIT
Как отмечено в комментариях, $i, безусловно, не лучшее имя для глобальной переменной. Если это будет использоваться в качестве простого «одноразового» преобразования, все может быть в порядке. Если нет, измените имя на то, что не конфликтует. Или поместите это как public static в классе.

Также существует preg_replace_callback(). Это лучше подходит, хотя я нахожу передачу имени функции в виде строки и оценку functionName('arg') почти одинаково уродливо:)

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