2013-03-26 37 views
2

我試圖鏈接Simple HTML DOM Parser find()遍歷HTML,但是當其中一個孩子不在時,它似乎崩潰。例如:(即,如果元件不處於HTML)PHP簡單的HTML Dom解析器find()在遍歷空元素時崩潰

$obj = $page->find('#headings', 0)->find('h4', 0)->nodes[0]; 

將導致PHP死()如果找到( '#標題',0)或找到( 'H4',0)返回null ,但如果所有元素都存在,則會成功。

有沒有辦法讓上面的鏈只是返回null而不是崩潰的PHP?我考慮修改simplehtmldom,但不知道如何。這一發現()函數如下:

// find dom node by css selector 
// Paperg - allow us to specify that we want case insensitive testing of the value of the selector. 
function find($selector, $idx=null, $lowercase=false) 
{ 
    return $this->root->find($selector, $idx, $lowercase); 
} 

編輯:(解決方案)

繼user1508519的建議,我已經創建了一個替代n查找()函數。通過這種方法,如果一個null屬性(與方法相反,find()方法在被鏈接時返回一個空節點),PHP仍然會通知一個通知,如果在鏈中被引用的更遠,但不會崩潰,因爲它會在使用find )。

// modified version of simple_html_dom->find() that will return an empty node instead of null when chained if an element is not found. simple_html_dom_node->nfind() must also be created for this to work. 
function nfind($selector, $idx=null, $lowercase=false) 
{ 
       $this->root->nfind($selector, $idx, $lowercase); 
} 

執行查找操作的實際代碼可以在simple_html_dom_node->找到(找到)和下面的函數應放在內部simple_html_dom_node整個包才能正常工作(最後一行僅修改 - 由於某種原因包裝原始的發現()函數,並仍然檢查is_null似乎崩潰PHP

//modifed version of simple_html_dom_node->find() 
function nfind($selector, $idx=null, $lowercase=false) 
{ 
    $selectors = $this->parse_selector($selector); 
    if (($count=count($selectors))===0) return array(); 
    $found_keys = array(); 

    // find each selector 
    for ($c=0; $c<$count; ++$c) 
    { 
     // The change on the below line was documented on the sourceforge code tracker id 2788009 
     // used to be: if (($levle=count($selectors[0]))===0) return array(); 
     if (($levle=count($selectors[$c]))===0) return array(); 
     if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); 

     $head = array($this->_[HDOM_INFO_BEGIN]=>1); 

     // handle descendant selectors, no recursive! 
     for ($l=0; $l<$levle; ++$l) 
     { 
      $ret = array(); 
      foreach ($head as $k=>$v) 
      { 
       $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; 
       //PaperG - Pass this optional parameter on to the seek function. 
       $n->seek($selectors[$c][$l], $ret, $lowercase); 
      } 
      $head = $ret; 
     } 

     foreach ($head as $k=>$v) 
     { 
      if (!isset($found_keys[$k])) 
       $found_keys[$k] = 1; 
     } 
    } 

    // sort keys 
    ksort($found_keys); 

    $found = array(); 
    foreach ($found_keys as $k=>$v) 
     $found[] = $this->dom->nodes[$k]; 

    // return nth-element or array 
    if (is_null($idx)) return $found; 
    else if ($idx<0) $idx = count($found) + $idx; 
    return (isset($found[$idx])) ? $found[$idx] : new simple_html_dom_node(''); 
} 
再次

感謝user1508519幫助我走到了所需的解決方案,同時提供一系列的同樣有效的選擇!評論,歡迎來解決方案/潛在副作用的有效性或者是否存在更多e任何人都應該有進一步的投入,這是一個完美的方法。

+1

可以預期的。每個階段都會返回一個對象,如果沒有任何內容,則返回一個對象不能使用任何東西作爲一個對象......如果你不能依賴那個文檔的結構是一致的並且總是可用的,那麼在深入研究之前,你必須解開並測試每個層次的結果。 – 2013-03-26 05:20:31

+0

'die()'?你的意思是它會拋出一個錯誤,因爲你試圖在'null'引用中查找一個屬性? – alex 2013-03-26 05:21:14

+0

@alex是的,但沒有錯誤拋出 - 我只是從錯誤發生的地方得到一個空白頁 – 2013-03-26 05:25:25

回答

1

你爲什麼要在連鎖店做?爲什麼不在隨後的檢查中檢查每個呼叫是否爲空?就像評論說的那樣,你不能對空對象進行操作。如果你正在做一個foreach循環,它將刪除對空檢查的需要。

$obj = $page->find('#headings', 0); 
if (!is_null($obj)) { 
    $obj = $page->find('h4', 0); 
    if (!is_null($obj)) 
     // ...continue... 
} 

編輯:

function find($selector, $idx=null, $lowercase=false) 
{ 
    if (is_null($this->root->find($selector, $idx, $lowercase))) 
    { 
     die("error"); 
     // throw exception? 
    } else // whatever 

} 

OR

編寫自己的包裝函數內部調用簡單的發現。

function wrapper($selector, $idx=null, $lowercase=false) { 
    // yep 
} 
+0

在鏈中它看起來更乾淨和更具可讀性 - 您的答案效果很好,foreach方法是一個好點,但理想情況下,我希望能夠以可預測的結果運行鏈(或者至少能夠處理錯誤)如果一個元素不存在 – 2013-03-26 05:44:02

+0

非常好 - 非常感謝您的幫助! – 2013-03-26 22:54:10

0

你可以這樣做:

$obj = ($h4 = $page->find('#headings h4', 0)) ? $h4->nodes[0] : null; 
相關問題