2

Simple HTML DOM Parser find()をチェーンしてHTMLをトラバースしようとしていますが、子の1つが存在しないとクラッシュするようです。例えば:

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

find('#headings'、0)またはfind('h4'、0)がnullを返す場合(つまり、要素がHTMLにない場合)、PHPはdie()になりますが、すべての要素が存在する場合は成功します。

PHPをクラッシュさせる代わりに、上記のチェーンが単にnullを返すようにする方法はありますか?simplehtmldomの変更を検討しましたが、方法がわかりません。find()関数を以下に示します。

// 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の提案に従って、代替のnfind()関数を作成しました。このアプローチでは、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->find()にあり、パッケージ全体が正しく機能するには、次の関数をsimple_html_dom_node内に配置する必要があります(最後の行のみが変更されます-何らかの理由で元のfind()関数をラップしますそれと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に再度感謝します!解決策/潜在的な副作用の有効性について、または誰かがさらに入力を持っている場合にこれを達成するためのよりエレガントな方法があるかどうかについてのコメントを歓迎します。

4

2 に答える 2

1

なぜあなたはそれを連鎖的にするのですか?各呼び出しがnullであるかどうか、後続のチェックをチェックインしてみませんか?コメントが言ったように、nullオブジェクトを操作することはできません。foreachループを実行している場合は、nullチェックが不要になります。

$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

}

また

simpleのfindを内部的に呼び出す独自のラッパー関数を記述します。

好き

function wrapper($selector, $idx=null, $lowercase=false) {
    // yep 
}
于 2013-03-26T05:26:40.433 に答える
0

あなたは次のようなことをすることができます:

$obj = ($h4 = $page->find('#headings h4', 0)) ? $h4->nodes[0] : null;
于 2013-03-26T06:47:37.643 に答える