[英]PHP DOMXPath problem
我正在嘗試使用 html 標簽解析文本塊,但我遇到了一些問題。
<?php
libxml_use_internal_errors(true);
$html = '
<html>
<body>
<div>
Message <b>bold</b>, <s>strike</s>
</div>
<div>
<span class="how">
<a href="link" title="text">Link</a>, <b> BOLD </b>
</span>
</div>
</body>
</html>
';
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->strictErrorChecking = false;
$dom->recover = true;
$dom->loadHTML($html);
function getMessages($element, $xpath)
{
$messages = array();
$children = $element->childNodes;
foreach ($children as $child)
{
if(strtolower($child->nodeName) == 'div')
{
// my functions
}
else
if ($child->nodeType == XML_TEXT_NODE)
{
$text = trim(DOMinnerHTML($element));
if($text)
{
$messages[] = array('type' => 'text', 'text' => $text);
}
}
}
return $messages;
}
function DOMinnerHTML($element)
{
$innerHTML = null;
$children = $element->childNodes;
foreach ($children as $child)
{
$tmp_dom = new DOMDocument();
$tmp_dom->appendChild($tmp_dom->importNode($child, true));
$innerHTML .= trim($tmp_dom->saveHTML());
}
return $innerHTML;
}
$xpath = new DOMXPath($dom);
$messagesXpath = $xpath->query("//div");
$messages = array();
$i = 0;
foreach($messagesXpath as $message)
{
$messages[] = getMessages($message, $xpath);
$i++;
if ($i == 2)
break;
}
var_dump($messages);
此代碼返回以下數組:
array(2) {
[0]=>
array(3) {
[0]=>
array(2) {
["type"]=>
string(4) "text"
["text"]=>
string(32) "Message<b>bold</b>,<s>strike</s>"
}
[1]=>
array(2) {
["type"]=>
string(4) "text"
["text"]=>
string(32) "Message<b>bold</b>,<s>strike</s>"
}
[2]=>
array(2) {
["type"]=>
string(4) "text"
["text"]=>
string(32) "Message<b>bold</b>,<s>strike</s>"
}
}
[1]=>
array(2) {
[0]=>
array(2) {
["type"]=>
string(4) "text"
["text"]=>
string(100) "<span class="how">
<a href="link" title="text">Link</a>, <b> BOLD </b>
</span>"
}
[1]=>
array(2) {
["type"]=>
string(4) "text"
["text"]=>
string(100) "<span class="how">
<a href="link" title="text">Link</a>, <b> BOLD </b>
</span>"
}
}
}
我想讓 $messages['text'] 帶有 html 標簽(沒關系),但由於某種原因,數組重復了!!!!
我認為這是這個街區的問題
if ($child->nodeType == XML_TEXT_NODE)
{
$text = trim(DOMinnerHTML($element));
if($text)
{
$messages[] = array('type' => 'text', 'text' => $text);
}
}
我認為您誤解了正在迭代哪些元素,因為您選擇了所有<div>
,然后將每個元素傳遞給getMessages
。 但是,在getMessages
中,您然后迭代每個<div>
的XML_TEXT_NODE
節點,這是雙重復制的來源。
讓我們以 HTML 為例:
<div>
Message <b>bold</b>, <s>strike</s>
</div>
DOM 元素和文本節點在邏輯上是不同的並且具有不同的類型 - XML_ELEMENT_NODE 和 XML_TEXT_NODE(完整列表請參見此處),因此<div>
實際上包含 5 個子節點(TEXT、ELEMENT、TEXT、ELEMENT、TEXT)。 您正確地確定了有問題的if
條件,但是僅將類型更改為 *XML_ELEMENT_NODE* 並不能完全解決問題。 仍然有多個子節點,其中每個<div>
的類型為 XML_ELEMENT_NODE。
為了完全解決這個問題,我更改了傳遞給getMessages
function 的元素,以便 function 可以在正確的級別進行迭代並消除重復。 我還通過重命名一些變量來消除一些復雜性以提高可讀性。
這是我的完整解決方案:
<?php
libxml_use_internal_errors(true);
$html = <<<HTML
<html>
<body>
<div>
Message <b>bold</b>, <s>strike</s>
</div>
<div>
<span class="how">
<a href="link" title="text">Link</a>, <b> BOLD </b>
</span>
</div>
</body>
</html>
HTML;
$dom = new DOMDocument();
$dom->preserveWhiteSpace = false;
$dom->strictErrorChecking = false;
$dom->recover = true;
$dom->loadHTML($html);
function getMessages($allDivs) {
$messages = array();
foreach ($allDivs as $div) {
if ($div->nodeType == XML_ELEMENT_NODE) {
$messages[] = trim(DOMinnerHTML($div));
}
}
return $messages;
}
function DOMinnerHTML($element) {
$innerHTML = null;
$children = $element->childNodes;
foreach ($children as $child) {
$tmp_dom = new DOMDocument();
$tmp_dom->appendChild($tmp_dom->importNode($child, true));
$innerHTML .= trim($tmp_dom->saveHTML());
}
return $innerHTML;
}
$xpath = new DOMXPath($dom);
$messagesXpath = $xpath->query("//div");
$messages[] = getMessages($messagesXpath);
print_r($messages);
?>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.