Si está bien formado el documento (o al menos bien formada-ish) se puede utilizar el DOM extension y xpath para buscar y reemplazar todos los elementos br por un nodo \ n de texto.
$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();
impresiones
<!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>
edición: versión más corta con sólo una iteració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);
$linebreak = $doc->createTextNode("\n");
foreach($xpath->query('//br') as $node) {
$node->parentNode->removeChild($node);
}
echo $doc->savehtml();
¿Estás seguro de que deseas reemplazar los elementos de salto de línea HTML/XHTML con saltos de línea físicos? Porque 'nl2br' no reemplaza los cortes de línea físicos, solo * agrega * elementos de salto de línea HTML/XHTML. – Gumbo
No estoy usando esta función para negar o recuperar una cadena devuelta desde nl2br. Lo estoy usando para desinfectar el texto en una base de datos heredada (desde una aplicación web que permitía html) antes de importarlo a mi base de datos. Acabo de decir lo contrario de nl2br porque la gente en general conoce esa función. – markb