HTML в обычный текст (для электронной почты) - PullRequest
8 голосов
/ 18 декабря 2009

Знаете ли вы хороший класс преобразования HTML в обычный текст написано в PHP?

Мне это нужно для преобразования тела письма HTML в текстовое тело письма.

Я написал простую функцию, но мне нужно больше функций, таких как преобразование таблиц, добавление ссылок в конце, преобразование вложенных списков…

- С уважением
takeshin

Ответы [ 7 ]

6 голосов
/ 18 декабря 2009

Я бы предложил использовать конвертер HTML в Markdown.

4 голосов
/ 18 декабря 2009

Определенная реализация отправки почты здесь просто порождает lynx с HTML и использует ее вывод для текстовой версии. Это не идеально, но работает. Вы также можете использовать ссылки или elinks .

3 голосов
/ 24 сентября 2012

Использование lynx возможно только в том случае, если у вас есть разрешение на запуск исполняемых файлов на сервере. Это, однако, не считается хорошей практикой. Кроме того, на защищенных хостах процесс php ограничен тем, что не может создавать сеансы bash, которые необходимы для запуска lynx.

Наиболее полное решение, написанное полностью на PHP, которое я смог найти, это класс Horde_Text_Filter_Html2text . Это часть из рамки Орды .

Другие решения, которые я пробовал:

Если кто-то нашел идеальное решение, пожалуйста, опубликуйте его для дальнейшего использования!

2 голосов
/ 02 июля 2018

Поскольку вопрос касается PHP, и я нашел c # код Дхармеша Хадияла весьма полезным, я преобразовал его в PHP.

(не могу комментировать, недостаточно репутации)

//From /1106651/html-v-obychnyi-tekst-dlya-elektronnoi-pochty#1106676
//converted from c# to PHP
class HtmlToText
{
    public static function stripHTML($source)
    {
        // Remove HTML Development formatting
        // Replace line breaks with space
        // because browsers inserts space
        $result = str_replace("\r",  " ",$source );
        // Replace line breaks with space
        // because browsers inserts space
        $result = str_replace("\n",  " ",$result );
        // Remove step-formatting
        $result = str_replace("\t",  "",$result );
        // Remove repeating spaces because browsers ignore them
        $result = preg_replace("/( )+/im",  " ", $result);


        // Remove html-Tag (prepare first by clearing attributes)
        $result = preg_replace("/<( )*html([^>])*>\s*/im",  "<html>", $result);

        $result = preg_replace("/(<( )*(\/)( )*html( )*>)/im",  "</html>", $result);

        $result = preg_replace("/(<html>)|(<\/html>)/im",  "", $result);

        // Remove the header (prepare first by clearing attributes)
        $result = preg_replace("/<( )*head([^>])*>/im",  "<head>", $result);

        $result = preg_replace("/(<( )*(\/)( )*head( )*>)/im",  "</head>", $result);

        $result = preg_replace("/(<head>).*(<\/head>)/im",  "", $result);


        // remove all scripts (prepare first by clearing attributes)
        $result = preg_replace("/<( )*script([^>])*>/im",  "<script>", $result);

        $result = preg_replace("/(<( )*(\/)( )*script( )*>)/im",  "</script>", $result);

        //$result = System.Text.RegularExpressions.Regex.Replace($result,
        //         "(<script>)([^(<script>\.</script>)])*(</script>)",
        //         "",
        //         System.Text.RegularExpressions.RegexOptions.IgnoreCase);
        $result = preg_replace("/(<script>).*(<\/script>)/im",  "", $result);


        // remove all styles (prepare first by clearing attributes)
        $result = preg_replace("/<( )*style([^>])*>/im",  "<style>", $result);

        $result = preg_replace("/(<( )*(\/)( )*style( )*>)/im",  "</style>", $result);

        $result = preg_replace("/(<style>).*(<\/style>)/im",  "", $result);


        // insert tabs in spaces of <td> tags
        $result = preg_replace("/<( )*td([^>])*>/im",  "\t", $result);


        // insert line breaks in places of <BR> and <LI> tags
        $result = preg_replace("/<( )*br( )*\/?>/im",  "\r", $result);

        $result = preg_replace("/<( )*li( )*>/im",  "\r", $result);


        // insert line paragraphs (double line breaks) in place
        // if <P>, <DIV> and <TR> tags
        $result = preg_replace("/<( )*div([^>])*>/im",  "\r\r", $result);

        $result = preg_replace("/<( )*tr([^>])*>/im",  "\r\r", $result);

        $result = preg_replace("/<( )*p([^>])*>/im",  "\r\r", $result);


        // Remove remaining tags like <a>, links, images,
        // comments etc - anything that's enclosed inside < >
        $result = preg_replace("/<[^>]*>/im",  "", $result);


        // replace special characters:
        $result = preg_replace("/ /im",  " ", $result);


        $result = preg_replace("/&bull;/im",  " * ", $result);

        $result = preg_replace("/&lsaquo;/im",  "<", $result);

        $result = preg_replace("/&rsaquo;/im",  ">", $result);

        $result = preg_replace("/&trade;/im",  "(tm)", $result);

        $result = preg_replace("/&frasl;/im",  "/", $result);

        $result = preg_replace("/&lt;/im",  "<", $result);

        $result = preg_replace("/&gt;/im",  ">", $result);

        $result = preg_replace("/&copy;/im",  "(c)", $result);

        $result = preg_replace("/&reg;/im",  "(r)", $result);

        // Remove all others. More can be added, see
        // http://hotwired.lycos.com/webmonkey/reference/special_characters/
        $result = preg_replace("/&(.{2,6});/im",  "", $result);


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

        // make line breaking consistent
        $result = str_replace("\n",  "\r",$result );

        // 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 = preg_replace("/(\r)( )+(\r)/im",  "\r\r", $result);

        $result = preg_replace("/(\t)( )+(\t)/im",  "\t\t", $result);

        $result = preg_replace("/(\t)( )+(\r)/im",  "\t\r", $result);

        $result = preg_replace("/(\r)( )+(\t)/im",  "\r\t", $result);

        // Remove redundant tabs
        $result = preg_replace("/(\r)(\t)+(\r)/im",  "\r\r", $result);

        // Remove multiple tabs following a line break with just one tab
        $result = preg_replace("/(\r)(\t)+/im",  "\r\t", $result);

        // Initial replacement target string for line breaks
        $breaks = "\r\r\r";
        // Initial replacement target string for tabs
        $tabs = "\t\t\t\t\t";
        for ($index = 0; $index < strlen($result); $index++)
        {
            $result = str_replace($breaks,  "\r\r",$result );
            $result = str_replace($tabs,  "\t\t\t\t",$result );
            $breaks = $breaks . "\r";
            $tabs = $tabs . "\t";
        }

        //remove spaces at the beginning of a line
        $result = preg_replace("/^ +/im",  "", $result);

        //line breaks at the beginning/end is probably unwanted. Coluld be left over by removing <html>/<head>/<body>
        $result = trim($result);

        // That's it.
        return $result;
    }
}
2 голосов
/ 08 марта 2012

Вы можете использовать lynx с опциями -stdin и -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";
}
1 голос
/ 02 июня 2014

В 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;
    }
}
1 голос
/ 13 апреля 2011

Я знаю, что вопрос касается PHP, но я использовал идею lynx, чтобы сделать эту подпрограмму Perl для преобразования HTML в текст:

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

отпечатков: Hi there Testing

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...