2009-12-18 14 views
8

¿Conoce alguna buena clase de conversión de HTML a texto sin formato escrita en PHP?HTML a texto sin formato (para correo electrónico)

Lo necesito para convertir cuerpo de correo HTML a cuerpo de correo de texto sin formato.

escribí función simple, pero necesito más funciones, como las tablas de conversión, añadir enlaces al final, la conversión de listas anidadas ...

- respecto
takeshin

+0

¿Por qué no enviar correo HTML? Entiendo que las tablas falsas son posibles en texto plano, pero cada lector de correo electrónico en el mundo lee HTML, ¿por qué no se ahorra la molestia de la conversión inútil porque usted u otra persona se niega a usar el correo HTML? – TravisO

+4

TravisO: No todos los lectores. Y algunos no convierten automáticamente HTML en texto sin formato. Para un usuario, el HTML sin formato generalmente no es agradable de leer :-) – Joey

+0

1996 ha terminado, acostumbrarse a él.Pero, por supuesto, los tipos elitistas que detestan el correo electrónico HTML van a ser los más elocuentes/dispuestos a votar esos ideales. – TravisO

Respuesta

6
+2

¿Y de qué sirve el descuento en un mensaje de texto? –

+1

Uh, ¿ha usado o leído algo sobre Markdown? "El objetivo primordial del diseño para la sintaxis de formato de Markdown es hacer que sea lo más legible posible. ** La idea es que un documento con formato de Markdown debería ser publicable tal como es, como texto sin formato, sin que parezca marcado con etiquetas o instrucciones de formateo. ** " – ceejayoz

+2

Markdownify es una buena solución, de hecho. Lo miré antes, pero pensé que no convierte las tablas. Pero el problema fue que probé en tablas con atributos '' y algunos estilos CSS. Despojé manualmente los subtítulos y atributos de clase y estilo, y funciona bien. – takeshin

3

Una implementación particular que envía el correo por aquí simplemente desova lynx con el HTML y utiliza su salida de la versión de texto. No es perfecto, pero funciona También puede usar links o elinks.

+0

Idea genial, me gusta. – ceejayoz

+0

Sí, esto ya fue sugerido en StackOverflow, pero estaba pidiendo alma de PHP. No tengo acceso a Lynx en mi servidor. Gracias. – takeshin

+0

Olvidó mencionar que necesita el '-dump' arg a lynx – JoelFan

1

Sé que la pregunta es acerca de PHP, pero he usado la idea de lince para hacer esta subrutina Perl para convertir HTML a texto:

use File::Temp; 

sub html2Txt { 
    my $html = shift; 
    my $htmlF = File::Temp->new(SUFFIX => '.html'); 
    print $htmlF $html; 
    close $htmlF; 
    return scalar `/usr/bin/lynx -dump $htmlF 2> /dev/null`; 
} 

print html2Txt '<b>Hi there</b> Testing'; 

impresiones: Hi there Testing

2

Usted puede utilizar el lince con -stdin y las opciones para lograr que -dump:

<?php 
$descriptorspec = array(
    0 => array("pipe", "r"), // stdin is a pipe that the child will read from 
    1 => array("pipe", "w"), // stdout is a pipe that the child will write to 
    2 => array("file", "/tmp/htmp2txt.log", "a") // stderr is a file to write to 
); 

$process = proc_open('lynx -stdin -dump 2>&1', $descriptorspec, $pipes, '/tmp', NULL); 

if (is_resource($process)) { 
    // $pipes now looks like this: 
    // 0 => writeable handle connected to child stdin 
    // 1 => readable handle connected to child stdout 
    // Any error output will be appended to htmp2txt.log 

    $stdin = $pipes[0]; 
    fwrite($stdin, <<<'EOT' 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head> 
<title>TEST</title> 
</head> 
<body> 
<h1><span>Lorem Ipsum</span></h1> 

<h4>"Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit..."</h4> 
<h5>"There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain..."</h5> 
<p> 
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque et sapien ut erat porttitor suscipit id nec dui. Nam rhoncus mauris ac dui tristique bibendum. Aliquam molestie placerat gravida. Duis vitae tortor gravida libero semper cursus eu ut tortor. Nunc id orci orci. Suspendisse potenti. Phasellus vehicula leo sed erat rutrum sed blandit purus convallis. 
</p> 
<p> 
Aliquam feugiat, neque a tempus rhoncus, neque dolor vulputate eros, non pellentesque elit lacus ut nunc. Pellentesque vel purus libero, ultrices condimentum lorem. Nam dictum faucibus mollis. Praesent adipiscing nunc sed dui ultricies molestie. Quisque facilisis purus quis felis molestie ut accumsan felis ultricies. Curabitur euismod est id est pretium accumsan. Praesent a mi in dolor feugiat vehicula quis at elit. Mauris lacus mauris, laoreet non molestie nec, adipiscing a nulla. Nullam rutrum, libero id pellentesque tempus, erat nibh ornare dolor, id accumsan est risus at leo. In convallis felis at eros condimentum adipiscing aliquam nisi faucibus. Integer arcu ligula, porttitor in fermentum vitae, lacinia nec dui. 
</p> 
</body> 
</html> 
EOT 
    ); 
    fclose($stdin); 

    echo stream_get_contents($pipes[1]); 
    fclose($pipes[1]); 

    // It is important that you close any pipes before calling 
    // proc_close in order to avoid a deadlock 
    $return_value = proc_close($process); 

    echo "command returned $return_value\n"; 
} 
3

Usando el lince es una opción sólo si tiene permiso para ejecutar archivos ejecutables en el servidor. Hacerlo, sin embargo, no se considera una buena práctica. Además, en hosts seguros, el proceso php está limitado para no generar sesiones bash, que son necesarias para ejecutar lince.

La solución más completa escrita completamente en PHP que pude encontrar es la clase Horde_Text_Filter_Html2text. Es una parte del Horde framework.

Otras soluciones que he probado son:

Si alguien tiene la solución perfecta, por favor, puesto que una vuelta para mayor referencia!

1

en C#:

private string StripHTML(string source) 
{ 
    try 
    { 
     string result; 

     // Remove HTML Development formatting 
     // Replace line breaks with space 
     // because browsers inserts space 
     result = source.Replace("\r", " "); 
     // Replace line breaks with space 
     // because browsers inserts space 
     result = result.Replace("\n", " "); 
     // Remove step-formatting 
     result = result.Replace("\t", string.Empty); 
     // Remove repeating spaces because browsers ignore them 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
                   @"()+", " "); 

     // Remove the header (prepare first by clearing attributes) 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*head([^>])*>", "<head>", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"(<()*(/)()*head()*>)", "</head>", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(<head>).*(</head>)", string.Empty, 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // remove all scripts (prepare first by clearing attributes) 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*script([^>])*>", "<script>", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"(<()*(/)()*script()*>)", "</script>", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     //result = System.Text.RegularExpressions.Regex.Replace(result, 
     //   @"(<script>)([^(<script>\.</script>)])*(</script>)", 
     //   string.Empty, 
     //   System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"(<script>).*(</script>)", string.Empty, 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // remove all styles (prepare first by clearing attributes) 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*style([^>])*>", "<style>", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"(<()*(/)()*style()*>)", "</style>", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(<style>).*(</style>)", string.Empty, 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // insert tabs in spaces of <td> tags 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*td([^>])*>", "\t", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // insert line breaks in places of <BR> and <LI> tags 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*br()*>", "\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*li()*>", "\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // insert line paragraphs (double line breaks) in place 
     // if <P>, <DIV> and <TR> tags 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*div([^>])*>", "\r\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*tr([^>])*>", "\r\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<()*p([^>])*>", "\r\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // Remove remaining tags like <a>, links, images, 
     // comments etc - anything that's enclosed inside < > 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"<[^>]*>", string.Empty, 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // replace special characters: 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @" ", " ", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&bull;", " * ", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&lsaquo;", "<", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&rsaquo;", ">", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&trade;", "(tm)", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&frasl;", "/", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&lt;", "<", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&gt;", ">", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&copy;", "(c)", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&reg;", "(r)", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     // Remove all others. More can be added, see 
     // http://hotwired.lycos.com/webmonkey/reference/special_characters/ 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       @"&(.{2,6});", string.Empty, 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // for testing 
     //System.Text.RegularExpressions.Regex.Replace(result, 
     //  this.txtRegex.Text,string.Empty, 
     //  System.Text.RegularExpressions.RegexOptions.IgnoreCase); 

     // make line breaking consistent 
     result = result.Replace("\n", "\r"); 

     // Remove extra line breaks and tabs: 
     // replace over 2 breaks with 2 and over 4 tabs with 4. 
     // Prepare first to remove any whitespaces in between 
     // the escaped characters and remove redundant tabs in between line breaks 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(\r)()+(\r)", "\r\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(\t)()+(\t)", "\t\t", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(\t)()+(\r)", "\t\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(\r)()+(\t)", "\r\t", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     // Remove redundant tabs 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(\r)(\t)+(\r)", "\r\r", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     // Remove multiple tabs following a line break with just one tab 
     result = System.Text.RegularExpressions.Regex.Replace(result, 
       "(\r)(\t)+", "\r\t", 
       System.Text.RegularExpressions.RegexOptions.IgnoreCase); 
     // Initial replacement target string for line breaks 
     string breaks = "\r\r\r"; 
     // Initial replacement target string for tabs 
     string tabs = "\t\t\t\t\t"; 
     for (int index = 0; index < result.Length; index++) 
     { 
      result = result.Replace(breaks, "\r\r"); 
      result = result.Replace(tabs, "\t\t\t\t"); 
      breaks = breaks + "\r"; 
      tabs = tabs + "\t"; 
     } 

     // That's it. 
     return result; 
    } 
    catch 
    { 
     MessageBox.Show("Error"); 
     return source; 
    } 
} 
Cuestiones relacionadas