2009-12-18 10 views
8

Connaissez-vous un bon HTML à la classe de conversion en texte brut écrit en PHP? J'en ai besoin pour convertir un corps de courrier HTML en corps de message texte brut.HTML au texte brut (pour l'email)

j'ai écrit fonction simple, mais je besoin de plus de fonctionnalités telles que les tables de conversion, en ajoutant des liens à la fin, la conversion des listes imbriquées ...

- ce qui a trait
takeshin

+0

Pourquoi ne pas simplement envoyer du courrier HTML? Je comprends que faire semblant des tables est un peu possible en texte clair mais chaque lecteur d'e-mail dans le monde lit le HTML, pourquoi ne pas vous épargner le problème de la conversion inutile parce que vous ou quelqu'un d'autre refuse d'utiliser le courrier HTML. – TravisO

+4

TravisO: Pas tous les lecteurs. Et certains ne convertissent pas automatiquement le HTML en texte brut. Pour un utilisateur, le HTML brut n'est généralement pas agréable à lire :-) – Joey

+0

1996 est terminée, faites-vous l'usage.Mais bien sûr, les types élitistes qui déteste les emails HTML vont être les plus enclins à voter ces idéaux. – TravisO

Répondre

6
+2

Et à quoi bon markdown dans un email texte? –

+1

Euh, avez-vous utilisé ou lu quelque chose sur Markdown? «L'objectif principal de la syntaxe de mise en forme de Markdown est de la rendre aussi lisible que possible. ** L'idée est qu'un document au format Markdown soit publiable tel quel, en texte brut, sans avoir l'air d'avoir été marqué avec des balises ou instructions de formatage. ** " – ceejayoz

+2

Markdownify est une bonne solution, en effet. Je l'ai regardé avant, mais je pensais qu'il ne convertit pas les tables. Mais le problème était, que j'ai essayé sur des tables avec des propriétés et des styles CSS. J'ai effacé manuellement les légendes et les caractères de classe et de style, et ça marche bien. – takeshin

3

Un courrier particulier l'envoi de la mise en œuvre ici fraie simplement lynx avec le code HTML et utilise sa sortie pour la version texte. Ce n'est pas parfait mais ça marche. Vous pouvez également utiliser links ou elinks.

+0

Idée soignée, j'aime bien. – ceejayoz

+0

Oui, cela a déjà été suggéré sur StackOverflow, mais je demandais PHP soultion. Je n'ai pas accès à Lynx à mon serveur. Merci. – takeshin

+0

Vous avez oublié de mentionner que vous avez besoin de l'argument '-dump' pour lynx – JoelFan

1

Je sais que la question est à propos de PHP, mais je l'idée de lynx pour faire de ce sous-programme Perl pour convertir le HTML en texte:

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'; 

impressions: Hi there Testing

2

Vous pouvez utiliser le lynx avec -stdin et les options -dump pour atteindre que:

<?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

Utiliser le lynx est une option que si vous avez la permission d'exécuter les fichiers exécutables sur le serveur. Ce faisant, cependant, n'est pas considéré comme une bonne pratique. De plus, dans les hôtes sécurisés, le processus php est limité pour être incapable de générer des sessions bash, qui sont nécessaires pour exécuter Lynx.

La solution la plus complète entièrement écrite en PHP que j'ai pu trouver est la classe Horde_Text_Filter_Html2text. C'est une partie du Horde framework.

D'autres solutions que j'ai essayé comprennent:

Si quelqu'un a la solution parfaite, s'il vous plaît, pour l'afficher de nouveau plus référence!

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; 
    } 
}