2011-04-01 25 views
35

No soy muy bueno con las expresiones regulares, pero con PHP quiero eliminar el atributo style de las etiquetas HTML en una cadena que vuelve de TinyMCE.Eliminar el atributo de estilo de las etiquetas HTML

Así que cambie <p style="...">Text</p> a solo <p>Test</p> vanilla <p>Test</p>.

¿Cómo puedo lograr esto con algo así como la función preg_replace()?

+4

usted ** no ** desea utilizar expresiones regulares para este . –

+3

Si no se recomiendan expresiones regulares para esta tarea, ¿qué * es *? –

+1

Usa los métodos DOM de php. – Maerlyn

Respuesta

106

La expresión regular pragmática (<[^>]+) style=".*?" va a resolver este problema en todos los casos razonables. La parte del partido que no es el primer grupo capturado debe ser eliminado, así:

$output = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $input); 

de ajuste de un < seguido por uno o más "no >" hasta que llegamos a la space y la parte style="...". El /i lo hace funcionar incluso con STYLE="...". Reemplace esta coincidencia con $1, que es el grupo capturado. Dejará la etiqueta como está, si la etiqueta no incluye style="...".

+1

+1 --- Acabo de usar esto para deshacerme del spam de estilo que ocurre en las páginas de Google Sites cuando los usuarios copian texto en el editor inteligente sin usar "Pegar como texto sin formato" en su navegador. Usé Notepad ++ y el comando de reemplazo. Para Notepad ++, el formato es '\ 1' y no' $ 1'. – Fuhrmanator

+0

no funciona cuando se escapa el estilo. Debe ser refactorizado para que funcione o $ input debe reemplazarse con stripcslashes ($ input) – bicycle

+8

Esto no funcionará con style = '...' – q0rban

-8

Podrías manejarlo desde el lado del cliente, lo más fácil sería con jQuery. Algo así como:

$("#tinyMce p").removeAttr("style"); 
+2

Eso es inseguro ya que el usuario aún puede manipular los datos enviados al servidor. – ThiefMaster

+0

El póster original preguntó cómo hacer esto con PHP, no con javascript. Cita: "... pero con PHP, quiero eliminar el atributo de estilo ..." –

4

Aquí van:

<?php 

$html = '<p style="border: 1px solid red;">Test</p>'; 
echo preg_replace('/<p style="(.+?)">(.+?)<\/p>/i', "<p>$2</p>", $html); 

?> 

Por cierto, como se ha señalado por otros, expresiones regulares no se sugieren para esto.

+2

'

' - BOOM. '

' - BOOM. – ThiefMaster

+1

Eso fue obviamente creado en el ejemplo reportado en la pregunta original. De todos modos, puedes mejorar la expresión regular usando algo como esto: preg_replace ('/

(. +?) <\/p>/i ', "

$ 4

", $ enlaces); y no obtener BOOM :) –

+0

@LorenzoMarcon gracias. Acabo de agregar la coincidencia inversa en función de su expresión regular comentada. – RafaSashi

35

Algo como esto debería funcionar (advertencia de código no probado):

<?php 

$html = '<p style="asd">qwe</p><br /><p class="qwe">qweqweqwe</p>'; 

$domd = new DOMDocument(); 
libxml_use_internal_errors(true); 
$domd->loadHTML($html); 
libxml_use_internal_errors(false); 

$domx = new DOMXPath($domd); 
$items = $domx->query("//p[@style]"); 

foreach($items as $item) { 
    $item->removeAttribute("style"); 
} 

echo $domd->saveHTML(); 
+10

+1 para usar una solución correcta, sin expresiones regulares – ThiefMaster

+0

confirmando que he probado este código y funciona. +1 – JaseC

+1

Además de mi comentario anterior ... Funciona, pero DOMDocument tiene problemas con las entidades html. Los convertirá en caracteres utf8. Entonces & comercio; se convierte en TM Al final utilicé simplehtmldom y puse mi función como respuesta ... – JaseC

2

Yo uso este:

function strip_word_html($text, $allowed_tags = '<a><ul><li><b><i><sup><sub><em><strong><u><br><br/><br /><p><h2><h3><h4><h5><h6>') 
{ 
    mb_regex_encoding('UTF-8'); 
    //replace MS special characters first 
    $search = array('/&lsquo;/u', '/&rsquo;/u', '/&ldquo;/u', '/&rdquo;/u', '/&mdash;/u'); 
    $replace = array('\'', '\'', '"', '"', '-'); 
    $text = preg_replace($search, $replace, $text); 
    //make sure _all_ html entities are converted to the plain ascii equivalents - it appears 
    //in some MS headers, some html entities are encoded and some aren't 
    //$text = html_entity_decode($text, ENT_QUOTES, 'UTF-8'); 
    //try to strip out any C style comments first, since these, embedded in html comments, seem to 
    //prevent strip_tags from removing html comments (MS Word introduced combination) 
    if(mb_stripos($text, '/*') !== FALSE){ 
     $text = mb_eregi_replace('#/\*.*?\*/#s', '', $text, 'm'); 
    } 
    //introduce a space into any arithmetic expressions that could be caught by strip_tags so that they won't be 
    //'<1' becomes '< 1'(note: somewhat application specific) 
    $text = preg_replace(array('/<([0-9]+)/'), array('< $1'), $text); 
    $text = strip_tags($text, $allowed_tags); 
    //eliminate extraneous whitespace from start and end of line, or anywhere there are two or more spaces, convert it to one 
    $text = preg_replace(array('/^\s\s+/', '/\s\s+$/', '/\s\s+/u'), array('', '', ' '), $text); 
    //strip out inline css and simplify style tags 
    $search = array('#<(strong|b)[^>]*>(.*?)</(strong|b)>#isu', '#<(em|i)[^>]*>(.*?)</(em|i)>#isu', '#<u[^>]*>(.*?)</u>#isu'); 
    $replace = array('<b>$2</b>', '<i>$2</i>', '<u>$1</u>'); 
    $text = preg_replace($search, $replace, $text); 
    //on some of the ?newer MS Word exports, where you get conditionals of the form 'if gte mso 9', etc., it appears 
    //that whatever is in one of the html comments prevents strip_tags from eradicating the html comment that contains 
    //some MS Style Definitions - this last bit gets rid of any leftover comments */ 
    $num_matches = preg_match_all("/\<!--/u", $text, $matches); 
    if($num_matches){ 
     $text = preg_replace('/\<!--(.)*--\>/isu', '', $text); 
    } 
    $text = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $text); 
return $text; 
} 
+4

Eso se ve ... Detallado –

19

me comentó en función @Mayerln 's. Funciona, pero DOMDocument realmente está lleno de codificación. Aquí está mi simplehtmldom versión

function stripAttributes($html,$attribs) { 
    $dom = new simple_html_dom(); 
    $dom->load($html); 
    foreach($attribs as $attrib) 
     foreach($dom->find("*[$attrib]") as $e) 
      $e->$attrib = null; 
    $dom->load($dom->save()); 
    return $dom->save(); 
} 
+1

Puede confirmar, esto funciona excelente! (Gracias por salvarme el día) – Mathlight

+2

¿Se puede mejorar esto para eliminar todos los atributos? – u01jmg3

1

Además de la respuesta de Lorenzo Marcon:

Usando preg_replace para seleccionar todo excepto atributo de estilo:

$html = preg_replace('/(<p.+?)style=".+?"(>.+?)/i', "$1$2", $html); 
Cuestiones relacionadas