【问题标题】:XPath/Domdocument check for child by class nameXPath/Domdocument 按类名检查子项
【发布时间】:2012-02-20 13:46:11
【问题描述】:

我试图在 DOMDocument 节点的循环中通过某个类名(类名 ='foo' 的 div)来查找子节点。如果存在,它应该将我的 foo 值设置为 1:

我的 HTML $document 看起来像:

...
<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() 可能不是正确的方法,但我已经尝试了不同的方法,但没有找到正确的方法。 :(

【问题讨论】:

    标签: php xpath domdocument


    【解决方案1】:

    根据您的评论

    嗯,是的,但不幸的是仍然无法正常工作。最终,我需要知道哪个 .posts div 具有子元素 'foo',因为我需要分析该父元素的内容,并且还需要稍后将其替换
    到上一个答案,您的谓词可能是:

    a) 选择 div 元素
    b) 具有属性 class=posts
    c) 并带有一个子元素 div
    d) 具有属性 class=foo

    作为 xpath 表达式:

    a) //div
    b) //div[@class="posts"]
    c) //div[@class="posts" 和 div ]
    d) //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>
    

    【讨论】:

    • VolkerK 非常感谢!我花了一段时间才通过,但它很有效! :-) 非常感谢!
    • 嗨,VolkerK,你知道我怎样才能找出替换元素的位置吗?例如DOM 树中的元素有哪个 nth.child() 或 eq()?像(伪)$post->appendChild..(...'the quick fox...'); $post->GetNthChildorEqNr#() ... // 会给我 2 和 4
    • 嗨,Volker,抱歉,这是后续行动。我在这里写了另一个问题:stackoverflow.com/questions/9465095/…。再次感谢!
    【解决方案2】:

    使用此 XPath 查找所有类为 foodiv 元素

    //div[@class = 'foo']
    

    更具体地说,使用这个:

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

    【讨论】:

    • 嗨基里尔,谢谢你的回答。但是,我希望能够检查父节点中是否存在“foo”div,而不是只获取类 foo 的“所有”div 元素。你知道怎么做吗?
    • @Mike,所以您可以使用第二个查询。它将返回所有 divfoo 类,前提是它们在 div 内,类 posts.
    • 嗯是的,但不幸的是仍然无法正常工作。最终我需要知道哪个 .posts div 有子元素 'foo' 因为我需要分析该父元素的内容,并且还需要稍后用 jquery 脚本 $(".posts:eq(1) > .foo 替换它").html()。第二个查询只会给我所有名为“foo”的 div 类,而不是它们的位置。你知道我的意思吗?
    • @Mike,也许这个 XPath 会帮助你://div[@class = 'posts'][div[@class = 'foo']]。它只选择包含div.foodiv.posts
    猜你喜欢
    • 2012-12-11
    • 1970-01-01
    • 2012-12-20
    • 2012-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 2017-10-05
    相关资源
    最近更新 更多