Сохранять разрывы строк внутри тегов с помощью DOMXPath?
В настоящее время я использую PHP и DOMXPath
для получения содержимого всех элементов <p>
веб-страницы:
<?php
...
$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXPath($doc);
$paragraphs = $xpath->evaluate("/html/body//p");
foreach ($paragraphs as $paragraph){
echo $paragraph->textContent . "<br />";
}
Моя проблема в том, что строка, полученная из textContent
, не учитывает теги <br />
, которые существуют в этих элементах <p>
. Вместо этого он удаляет разрыв строки и объединяет слова, которые обычно находятся в отдельных строках. Например:
Пример HTML:
<p>
Some happy talk goes here talking about our great product.<br />
We would love for you to buy it!
</p>
<p>
Random information and what not<br />
Isn't that cool?
</p>
Текущий вывод из PHP выше:
Some happy talk about our great product.We would love for you to buy it!
Random information and what notIsn't that cool?
Я тоже пробовал $paragraphs = $doc->getElementsByTagName("p");
и это дает мне то же самое.
Есть ли способ заставить DOMXPath/DOMDocument сохранять разрывы строк? Мне нужно уметь отделять каждое слово в абзаце, и текущий вывод запрещает это.
Если есть альтернативный метод извлечения строки из элементов <p>
с сохранением <br />
или '\n'
, это также было бы здорово.
РЕДАКТИРОВАТЬ
При дальнейшем исследовании рассматриваемый HTML-код на самом деле представляет собой список якоря, разделенные тегами <br>
, но без фактических разрывов строк:
<p class="home_page_list"><a href="/home/personal-banking/checking/Category-Page-Classic-Checking/classic-checking.html">Classic Checking</a><br> <a href="/home/personal-banking/checking/Category-Page-Interest-Checking/interest-checking.html">Interest Checking</a><br> <a href="/home/personal-banking/checking/Category-Page-Interest-Checking/interest-premium-checking.html">Premium Checking</a><br> <a href="/home/personal-banking/Savings-Category-Page/Basic-Savings-Category-Page/basic-savings.html">Savings Plans</a><br> <a href="/home/personal-banking/Savings-Category-Page/Money-Market-Accounts-Category-Page/money-market-accounts.html">Money Market Accounts</a><br> <a href="/home/personal-banking/Savings-Category-Page/Certificates-of-Deposit-Category-Page/fixed-rate-CD.html">CDs</a><br> <a href="/home/personal-banking/Savings-Category-Page/Individual-Retirement-Account-Category-Page/individual-retirement-account.html">IRAs</a></p>
Оказывается, это правильно работает с исходным заданным HTML.
ОБНОВЛЕНИЕ: Решено
С помощью ответа @ircmaxell и комментариев, оставленных @netcoder и @Gordon, это было решено, это не очень элегантно, но пока сойдет.
Пример:
foreach ($paragraphs as $paragraph){
$p_text = new DOMDocument();
$p_text->loadHTML(str_ireplace(array("<br>", "<br />"), "\r\n", DOMinnerHTML($paragraph)));
//Do whatever, in this case get all of the words in an array.
$words = explode(" ", str_ireplace(array(",", ".", "&", ":", "-", "\r\n"), " ", $p_text->textContent));
print_r($words);
}
При этом используется dominnerhtml (как предложено @netcoder) для замены экземпляры <br>
с "\r\n" (как предложено @ircmaxell), которые затем могут быть оценены после textContent.
Очевидно, что есть некоторые возможности для улучшения, но это решило мою текущую проблему.
Спасибо всем за помощь,
Бен
3 answers
Ну, что я бы сделал, так это заменил разрывы строк буквальными разрывами строк:
$doc = new DOMDocument();
$doc->loadHTML($html);
$brs = $doc->getElementsByTagName('br');
foreach ($brs as $node) {
$node->parentNode->replaceChild($doc->createTextNode("\r\n"), $node);
}
$xpath = new DOMXPath($doc);
$paragraphs = $xpath->evaluate("/html/body//p");
foreach ($paragraphs as $paragraph){
echo $paragraph->textContent . "<br />";
}
Одна из возможностей
echo simplexml_import_dom($paragraph)->asXML();
У меня такая же ситуация, я использую:
$document->loadHTML(str_replace('<br>', urlencode('<br>'), $string_or_file));
И я использую urlencode(), чтобы изменить его обратно для отображения или вставки в базу данных.