簡體   English   中英

PHP DOMXPath問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM