Проверка XPath / Domdocument для дочернего элемента по имени класса - PullRequest
1 голос
/ 20 февраля 2012

Я пытаюсь найти дочерние узлы по определенному имени класса (div с именем класса = 'foo') в цикле узлов DOMDocument. Если он существует, он должен установить для моего значения foo значение 1:

Мой документ HTML $ выглядит так:

...
<div class="posts">Div Posts 1</div>
<div class="posts">Div Posts 2<div class="foo"></div></div>
<div class="posts">Div Posts 3</div>
<div class="posts">Div Posts 4<div class="foo"></div></div>
<div class="posts">Div Posts 5</div>
...

DOMDocument / Xpath ($ document):

$html = array();
$document = new \DOMDocument();
$document->loadHTMLFile($url); // loads html from above
$xpath = new \DOMXPath($document);

$i=0;
foreach ($xpath->query(Parser::cssToXpath('.posts')) as $node) {
    $html['posts'][$i]['content'] = $node->nodeValue;  
    // check if child node with class name 'foo' exists => doesn't work :(
    $children = $node->getElementsByTagName('foo');
    if($children)
        $html['posts'][$i]['foo'] = '1';
    else
        $html['posts'][$i]['foo'] = '0';
    $i++;
}

Выход:

[posts] => Array
    (
        [0] => Array
            (
                [content] => Div class Posts 1
                [foo] => 1
            )

        [1] => Array
            (
                [content] => Div class Posts 2
                [foo] => 1
            )

        [2] => Array
            (
                [content] => Div class Posts 3
                [foo] => 1
            )

        [3] => Array
            (
                [content] => Div class Posts 4
                [foo] => 1
            )

        [4] => Array
            (
                [content] => Div class Posts 5
                [foo] => 1
            )

    )

getElementsByTagName () может не подходить для этого, но я уже пробовал разные методы и не нашел правильный. (

Ответы [ 2 ]

2 голосов
/ 20 февраля 2012

Согласно вашему комментарию

Хм да, но, к сожалению, все еще не работает. В конце концов мне нужно знать, у какого .posts div есть дочерний элемент 'foo', потому что мне нужно проанализировать содержимое этого родителя, а также заменить его позже
на предыдущий ответ, которым ваш предикат, вероятно, является:

а) выберите элементы div
б) с атрибутом class = posts
в) и с дочерним элементом div
г) который имеет атрибут class = foo

как выражение xpath:

а) // div
б) // div [@ class = "posts"]
в) // div [@ class = "posts" и div]
г) // div [@ class = "posts" и div [@ class = "foo"]]

, например

<?php
$doc = new DOMDocument;
$doc->loadhtml( getData() );
$xpath = new DOMXPath($doc);   

/*
use something like
    //div[contains(concat(' ',normalize-space(@class),' '),' post ')]
if the html element may have class="post lalala"
*/
foreach( $xpath->query('//div[@class="posts" and div[@class="foo"]]') as $post) {
    while ( $post->firstChild ) {
        $post->removeChild( $post->firstChild );
    }   
    $post->appendChild( $doc->createElement('span', 'The quick fox....') );
}
echo $doc->savehtml();


function getData() {
    return <<< eoh
<html><head><title>...</title></head><body>
    <div class="posts">Div Posts 1</div>
    <div class="posts">Div Posts 2<div class="foo"></div></div>
    <div class="posts">Div Posts 3</div>
    <div class="posts">Div Posts 4<div class="foo"></div></div>
    <div class="posts">Div Posts 5</div>
</body></html>
eoh;
}

печать

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>...</title></head><body>
    <div class="posts">Div Posts 1</div>
    <div class="posts"><span>The quick fox....</span></div>
    <div class="posts">Div Posts 3</div>
    <div class="posts"><span>The quick fox....</span></div>
    <div class="posts">Div Posts 5</div>
</body></html>
1 голос
/ 20 февраля 2012

Используйте этот XPath, чтобы найти все div элементы с классом foo

//div[@class = 'foo']

Чтобы быть более точным, используйте это:

//div[@class = 'posts']/div[@class = 'foo']
...