Как заменить все разрывы строк XHTML/HTML (‹br›) новыми строками?

Я ищу лучшую функцию br2nl. Я хотел бы заменить все экземпляры <br> и <br /> новыми строками \n. Очень похоже на функцию nl2br(), но наоборот.

Я знаю, что в комментариях к руководству по PHP есть несколько решений, но я ищу отзывы от сообщества SO о возможных решениях.


person markb    schedule 12.03.2010    source источник
comment
Вы уверены, что хотите заменить элементы разрыва строки HTML/XHTML физическими разрывами строк? Потому что nl2br не заменяет физические разрывы строк, а просто добавляет элементы разрыва строк HTML/XHTML.   -  person Gumbo    schedule 13.03.2010
comment
Я не использую эту функцию для отмены или восстановления строки, которая была возвращена из nl2br. Я использую его для очистки текста в устаревшей базе данных (из веб-приложения, в котором разрешен html), прежде чем импортировать его в свою базу данных. Я просто сказал противоположное nl2br, потому что люди обычно знают эту функцию.   -  person markb    schedule 13.03.2010


Ответы (4)


Обычно я бы сказал "не используйте регулярное выражение для работы с HTML", но в этом случае я, вероятно, выбрал бы регулярное выражение, учитывая, что теги <br> обычно выглядят так:

  • <br>
  • или <br/> с любым количеством пробелов перед /


Я полагаю, что что-то вроде этого поможет:

$html = 'this <br>is<br/>some<br />text <br    />!';
$nl = preg_replace('#<br\s*/?>#i', "\n", $html);
echo $nl;

Пара замечаний:

  • начинается с <br
  • за которым следует любое количество белых символов: \s*
  • опционально, / : /?
  • и, наконец, >
  • и это с использованием совпадения без учета регистра (#i), поскольку <BR> будет допустимым в HTML
person Pascal MARTIN    schedule 12.03.2010
comment
Это отличное объяснение регулярного выражения. - person Echo says Reinstate Monica; 13.03.2010
comment
Чтобы быть очень придирчивым =] : <input type="text" value="<br />"> разрешено в html (не xhtml). А в разделе CDATA <br /> это обычный текст. - person VolkerK; 13.03.2010
comment
@VolkerK: хм, правда :-) ;; Я писал это, используя DOM, и когда я закончил, я увидел, что вы опубликовали такое же решение, которое я бы предложил (за исключением того, что я использовал getElementsByName, а не XPath), поэтому не опубликовал его - - может быть, мне следует отредактировать свой ответ для полноты, поскольку он был принят... - person Pascal MARTIN; 13.03.2010
comment
Но это решение быстрее и меньше потребляет памяти (если это имеет значение). Если у вас нет полностью произвольных документов, я, вероятно, сочту эти крайние случаи приемлемыми. - person VolkerK; 13.03.2010
comment
Разве вторым аргументом не должен быть \\n? это единственное, что работает на моей установке здесь. - person jonathanKingston; 19.07.2012
comment
Мой HTML выглядит так: ‹br style=color: rgb(34, 34, 34); семейство шрифтов: Open Sans, Helvetica Neue, Helvetica, Arial, без засечек; размер шрифта: 15px;› - person Konstantin XFlash Stratigenas; 19.10.2019

Вы должны использовать константу PHP_EOL, чтобы иметь независимые от платформы новые строки.

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

$newlineTags = array(
  '<br>',
  '<br/>',
  '<br />',
);
$html = str_replace($newlineTags, PHP_EOL, $html);

Я знаю, что у этого решения есть некоторые недостатки, но все же хотел поделиться своими мыслями.

person Antti    schedule 25.08.2014
comment
А регулярные выражения обычно требуют более тяжелых вычислений. - person Billal Begueradj; 24.09.2017
comment
@BenBITDesign Что касается предложенного вами редактирования, обратите внимание, что абсолютно неверно, что регулярное выражение в целом требует дополнительных вычислений. На самом деле, без учета времени для этого конкретного случая вполне вероятно, что механизм PCRE может выполнить эту замену более эффективно, чем str_replace, особенно когда включена компиляция точно в срок. - person Konrad Rudolph; 31.10.2019

Если документ правильно сформирован (или, по крайней мере, правильно сформирован), вы можете использовать расширение DOM и xpath, чтобы найти и заменить все элементы br текстовым узлом \n.

$in = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>...</title></head><body>abc<br />def<p>ghi<br />jkl</p></body></html>';

$doc = new DOMDOcument;
$doc->loadhtml($in);
$xpath = new DOMXPath($doc);

$toBeReplaced = array();
foreach($xpath->query('//br') as $node) {
    $toBeReplaced[] = $node;
}

$linebreak = $doc->createTextNode("\n");
foreach($toBeReplaced as $node) {
    $node->parentNode->replaceChild($linebreak->cloneNode(), $node);
}

echo $doc->savehtml();

отпечатки

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head><title>...</title></head>
<body>abc
def<p>ghi
jkl</p>
</body>
</html>

редактировать: более короткая версия только с одной итерацией

$in = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>...</title></head><body>abc<br />def<p>ghi<br />jkl</p></body></html>';

$doc = new DOMDOcument;
$doc->loadhtml($in);
$xpath = new DOMXPath($doc);

$linebreak = $doc->createTextNode("\n");
foreach($xpath->query('//br') as $node) {
  $node->parentNode->removeChild($node);
}

echo $doc->savehtml();
person VolkerK    schedule 12.03.2010
comment
Вам не нужно делать два раунда. Вы можете заменить узлы первыми foreach. - person Gumbo; 13.03.2010
comment
Кажется, это так ;-) По какой-то (неизвестной) причине я вспомнил об этом, чтобы сломать итератор xpath. - person VolkerK; 13.03.2010
comment
Более короткая версия не добавляет узел $linebreak. В любом случае, это именно то, что мне было нужно, спасибо. - person TechNyquist; 26.05.2020

Из комментариев nl2br:

<?php
function br2nl($string){
  $return=eregi_replace('<br[[:space:]]*/?'.
    '[[:space:]]*>',chr(13).chr(10),$string);
  return $return;
}
?> 
person ssergei    schedule 12.03.2010
comment
модуль регулярных выражений posix устарел. Со страницы руководства ereg_replace: эта функция УСТАРЕЛА, начиная с PHP 5.3.0, и УДАЛЕНА, начиная с PHP 6.0.0. Надеяться на эту функцию крайне не рекомендуется. - person VolkerK; 13.03.2010