DomCrawler filterXpath для электронных писем - PullRequest
0 голосов
/ 20 января 2020

В моем проекте я пытаюсь использовать filterXPath для электронных писем. Поэтому я получаю электронное письмо через IMAP и помещаю тело письма в мою DomCrawler.

$crawler = new Crawler();
$crawler->addHtmlContent($mail->textHtml); //mail html content utf8

Теперь к моей проблеме. Мне нужен только простой текст почтового тела, но все еще остаются все новые пробелы и т. Д. c - точно так же, как письмо выглядит просто в виде обычного текста без html (все еще с \ n \ r и c) .

По этой причине я пытался использовать $crawler->filterXPath('//body/descendant-or-self::*/text()') для получения каждого текстового узла внутри почты.

Однако мой тестовый почтовый ящик содержит html, например:

<p>&#13;
    <u>
        <span>
            <a href="mailto:mail@example.com">
                <span style="color:#0563C1">mail@example.com</span>
            </a>
        </span>
    </u>
    <span>&#13;</span>
    <span>·</span>
    <span>
        <b>
            <a href="http://www.example.com">
                <span style="color:#0563C1">www.example.com</span>
            </a>
        </b>
    <p/>
    </span>
</p>&#13;

В моей почте это выглядит как mail@example.com · www.example.com (в одну строку).

С моим filterXPath я получаю несколько узлов, что приводит к следующим (несколько строк):

mail@example.com
· wwww.example.com

Я знаю, что, возможно, проблема &#13; может быть \r, но, поскольку я не могу изменить html в почте, мне нужно другое решение - , как упоминалось ранее в письме. только одна строка .

Имейте в виду, что мое решение должно работать для каждой почты - я не знаю, как выглядит почта html - она ​​может меняться каждый время. Поэтому мне нужно универсальное c решение.

Я уже пытался использовать strip_tags - это совсем не меняет результат.


Мой текущий подход:

$crawler = new Crawler();
$crawler->addHtmlContent($mail->textHtml);

$text = "";
foreach ($crawler->filterXPath('//body/descendant-or-self::*/text()') as $element) {
    $part = trim($element->textContent);
    if($part) {
        $text .= "|".$part."|\n"; //to see whitespaces etc
    }
}
echo $text;

//OUTPUT
|mail@example.com|
|·|
| |
|www.example.com|
| |

Ответы [ 2 ]

0 голосов
/ 21 января 2020

Мне кажется, что-то вроде этого должно работать:

$xpath = new DOMXpath($crawler);
$result = $xpath->query('(//span[not(descendant::*)])');

$text = "";
foreach ($result as $element) {
    $part = trim($element->textContent);
    if($part) {
        $text .= "|".$part."|"; //to see whitespaces etc
    }
}
echo $text;

Вывод:

|mail@example.com||·||www.example.com|
0 голосов
/ 21 января 2020

Обращаем ваше внимание, что вы имеете дело с двумя различными способами обработки только текстовых узлов с пробелами: HTML имеет свои собственные правила о том, визуализируются ли они (разница в основном между блочными элементами и встроенными элементами, а также включает нормализацию) и XPATH работает над деревом документов, предоставляемым синтаксическим анализатором (или API DOM), который имеет свою собственную конфигурацию сохранения или пропуска только этих пробельных текстовых узлов. Принимая это во внимание, одним из решений может быть использование функции string() для получения строкового значения элемента, содержащего адрес электронной почты:

Для этого ввода:

<root>
<p>&#13;
    <u>
        <span>
            <a href="mailto:mail@example.com">
                <span style="color:#0563C1">mail@example.com</span>
            </a>
        </span>
    </u>
    <span>&#13;</span>
    <span>·</span>
    <span>
        <b>
            <a href="http://www.example.com">
                <span style="color:#0563C1">www.example.com</span>
            </a>
        </b>
    <p/>
    </span>
</p>&#13;
</root>

Это выражение XPath:

string(/root)

Выходы:





                mail@example.com




    ·



                www.example.com





Регистрация здесь

...