Using multiple find in foreach with QueryPath

五迷三道 提交于 2019-12-04 13:14:40

I'm just learning QueryPath myself, but I think you should branch the row object. Otherwise the $tr->find('.eventdate') will take you to the abbr element contained in the row, and each following find() will try to find elements beneath the abbr, resulting in no matches. branch() (see documentation) creates a copy of the QueryPath object, leaving the original object (in this case $tr) intact.

So your code would be:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule')->find('tr') as $tr){
    echo 'date: ';
    echo $tr->branch()->find('.eventdate')->text();
    echo ' time: ';
    echo $tr->branch()->find('.dtstart')->text();
    echo '<br>';
}

I don't know if this is the preferred way to achieve what you want, but it seems to work.

QueryPath maintains its state internally (unlike jQuery) for performance reasons. So branch() is the way to go.

As a modification to the proposed solution, though, I would suggest minimizing the number of find() calls by doing this:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule tr') as $tr){
    echo 'date: ';
    echo $tr->branch('.eventdate')->text();
    echo ' time: ';
    echo $tr->branch('.dtstart')->text();
    echo '<br>';
}

Finally, any time you do a "destructive" action (like a find()), you can always go back one step using end(). So the above could also be done like this:

$qp = htmlqp($url);
foreach ($qp->find('table#schedule tr') as $tr){
    echo 'date: ';
    echo $tr->find('.eventdate')->text();
    echo ' time: ';
    echo $tr->end()->find('.dtstart')->text();
    echo '<br>';
}

This is a VERY VERY minor performance improvement, but I prefer the branch() method unless I'm working with documents larger than 1M.

In QueryPath 3.x, which has a whole bunch of new performance enhancements, I am toying with the idea of going with the jQuery way of creating a new object for each function. Unfortunately, this method will use a LOT more memory, so I may not keep it. While branch() takes a little while to learn, it does have its advantages.

yeah you are right, I actually had this problem today, in jquery, you just query, query, query, query no problems, however QueryPath if you query, it changes the internal "state" of the object so if you attempt a second query, it's applied against the current state.

so if you want to query multiple "separate" locations in the document, you have to branch before

$q = qp("something.html);
$a = $q->branch()->find("tr");
$b = $q->branch()->find("a");

that seems to work in my code, so I suppose it will work in yours.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!