2010-03-12 19 views
34

Estoy buscando la mejor función de br2nl. Me gustaría reemplazar todas las instancias de <br> y <br /> con nuevas líneas \n. Al igual que la función nl2br(), pero al revés.Cómo reemplazar todos los saltos de línea XHTML/HTML (<br>) con nuevas líneas?

Sé que hay varias soluciones en los comentarios manuales de PHP, pero estoy buscando comentarios de la comunidad SO sobre posibles soluciones.

+1

¿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

+0

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

Respuesta

88

yo diría que en general "no utilizan expresiones regulares para trabajar con HTML", pero, en este caso, probablemente me iría con una expresión regular, teniendo en cuenta que <br> etiquetas generalmente se parecen a cualquiera:

  • <br>
  • o <br/>, con cualquier número de espacios antes de la /


Supongo que algo como esto haría el truco:

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

par de notas:

  • comienza con <br
  • seguido de cualquier número de caracteres blancos: \s*
  • optionnaly, un /: /?
  • y, finalmente, >
  • y esto utilizando un partido entre mayúsculas y minúsculas (#i), como <BR> sería válido en HTML
+1

Esa es una gran explicación de la expresión regular. – Echo

+11

+1 para descomponer la expresión regular. – markb

+2

Para ser muy quisquilloso =]: '' está permitido en html (no xhtml). Y en una sección CDATA '
' es texto "normal". – VolkerK

1

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(); 
+0

No necesita hacer dos rondas. Puede reemplazar los nodos con el primer 'foreach'. – Gumbo

+0

Eso parece ser así ;-) Por alguna razón (desconocida), lo recordé para romper el iterador xpath. – VolkerK

0

De los nl2br comentarios:

<?php 
function br2nl($string){ 
    $return=eregi_replace('<br[[:space:]]*/?'. 
    '[[:space:]]*>',chr(13).chr(10),$string); 
    return $return; 
} 
?> 
+7

el módulo de expresión regular posix ha quedado en desuso. Desde la página de ereg \ _replace manual: "Esta función ha sido DEPURADA a partir de PHP 5.3.0 y RETIRADA a partir de PHP 6.0.0. Se desaconseja confiar en esta característica". – VolkerK

5

Debería utilizar PHP_EOL constante para tener nuevas líneas independientes de la plataforma.

En mi opinión, usar funciones que no sean de expresiones regulares siempre que sea posible hace que el código sea más legible.

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

Soy consciente de que esta solución tiene algunas fallas, pero quería compartir mis conocimientos.

+1

Y las expresiones regulares requieren generalmente cálculos más pesados. –

Cuestiones relacionadas