Выбрать следующий узел выбранного узла в PHP DOM? - PullRequest
7 голосов
/ 03 марта 2012

Пока я работаю над HTML-файлом, подобным этому

<div name="node"></div>
<div></div>
<div name="node"></div>
<div></div>
<div name="node"></div>
<div></div>

Я хочу выбрать следующий узел каждого "div", имя которого равно "node", и я пытаюсь:

$dom = new DOMdocument();
@$dom->loadHTML($html);
$xpath = new DOMXPath($dom);

$els = $xpath->query("//div[@name='node']");

$j = 0;

foreach($els as $el)
{
    if($el->next_sibling()) $j++;
}

echo $j;

Но я просто получаю сообщение об ошибке

Неустранимая ошибка: вызов неопределенного метода DOMElement :: next_sibling ()

Может кто-нибудь сказать мне, что не так с моим сценарием, пожалуйста?

Ответы [ 4 ]

17 голосов
/ 04 марта 2012

Ошибка вполне понятна: нет способа DOMElement::next_sibling(). Прочитайте документацию для DOMElement и его родительского класса DOMNode. Вы думаете о свойстве DOMNode::nextSibling.

Однако nextSibling получает следующий узел , а не следующий элемент . (Нет метода или свойства DOM, которое получает следующий элемент. Вам нужно продолжать использовать nextSibling и проверять nodeType, пока вы не нажмете другой элемент.) Ваш вопрос говорит, что вы хотите следующий узел, но я думаю, что вы на самом деле хотите следующий элемент (пустой <div>). Это на самом деле довольно легко сделать с XPath, так почему бы вам не сделать это вместо этого?

Чтобы получить его немедленно:

$els = $xpath->query("//div[@name='node']/following-sibling::*[1]");

Чтобы получить его, когда у вас уже есть <div name="node">:

$nextelement = $xpath->query("following-sibling::*[1]", $currentdiv);
6 голосов
/ 03 марта 2012

В DOM нет функции под названием next_sibling (). Вам следует использовать свойство nextSibling, определенное в DOMNode (http://www.php.net/manual/en/class.domnode.php).

foreach($els as $el)
{
    if($el->nextSibling) $j++;
}
4 голосов
/ 04 марта 2012

Я не знаю php, но это xpath получает их:

//div[@name="node"]/following-sibling::*[1]
1 голос
/ 23 марта 2014

Игнорирование текстовых узлов (надеюсь, не проверено)

foreach($els as $el){
  $next = $el->nextSibling;
  while($next){
    if($next->nodeType!==3){
       $j++;
       break;
    }
    $next = $next->nextSibling;
  }
}

Как функция

function nextElement($node, $name=null){
    if(!$node){
        return null;
    }
    $next = $node->nextSibling;
    if(!$next){
        return null;
    }
    if($next->nodeType === 3){
        return self::nextElement($next, $name);
    }
    if($name && $next->nodeName !== $name){
        return null;
    }
    return $next;
}

Использование

foreach($els as $el)
{
    if(nextElement($el,'div')) $j++;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...