如何使用dom xpath选择具有相同标签的第二个元素?

时间:2014-10-10 06:56:19

标签: php html xpath domdocument

我有这样的布局:

<div class="fly">
    <img src="a.png" class="badge">
    <img class="aye" data-original="b.png" width="130" height="253" />        
         <div class="to">
              <h4>Fly To The Moon</h4>
                  <div class="clearfix">
                       <div class="the">
                            <h4>**Wow**</h4>
                       </div>
                       <div class="moon">
                            <h4>**Great**</h4>                      
                       </div>
                   </div>
          </div>
</div>

首先我从xpath获取查询:

$a = $xpath->query("//div[@class='fly']""); //to get all elements in class fly    
foreach ($a as $p) {
     $t = $p->getElementsByTagName('img');
     echo ($t->item(0)->getAttributes('data-original'));
}

当我运行代码时,它将产生0结果。跟踪后,我发现首先处理<img class="badge">。我想问一下,如何从<img class="aye">获取数据原始值并获得值&#34; &#34;和&#34; 伟大&#34;来自<h4>代码?

谢谢,

3 个答案:

答案 0 :(得分:1)

Alernatively,您可以使用另一个xpath查询来添加当前代码。

要获取该属性,请使用->getAttribute()

$dom = new DOMDocument();
$dom->loadHTML($markup);
$xpath = new DOMXpath($dom);
$parent_div = $xpath->query("//div[@class='fly']"); //to get all elements in class fly

foreach($parent_div as $div) {
    $aye = $xpath->query('./img[@class="aye"]', $div)->item(0)->getAttribute('data-original');
    echo $aye . '<br/>'; // get the data-original
    $others = $xpath->query('./div[@class="to"]/div[@class="clearfix"]', $div)->item(0);
    foreach($xpath->query('./div/h4', $others) as $node) {
        echo $node->nodeValue . '<br/>'; // echo the two h4 values
    }
    echo '<hr/>';
}

Sample Output

答案 1 :(得分:1)

感谢您的代码!

我尝试了代码,但它失败了,我不知道为什么。所以,我改变了一些你的代码并且它有效!

$dom = new DOMDocument();
$dom->loadHTML($markup);
$xpath = new DOMXpath($dom);
$parent_div = $xpath->query("//div[@class='fly']"); //to get all elements in class fly

foreach($parent_div as $div) {
    $aye = $xpath->query('**descendant::**img[@class="aye"]', $div)->item(0)->getAttribute('data-original');
    echo $aye . '<br/>'; // get the data-original
    $others = $xpath->query('**descendant::**div[@class="to"]/div[@class="clearfix"]', $div)->item(0);
    foreach($xpath->query('.//div/h4', $others) as $node) {
        echo $node->nodeValue . '<br/>'; // echo the two h4 values
    }
    echo '<hr/>';
}

我不知道./descendant之间的区别是什么,但我的代码可以使用descendant正常工作。

答案 2 :(得分:0)

给出以下XML:

<div class="fly">
    <img src="a.png" class="badge">
    <img class="aye" data-original="b.png" width="130" height="253" />        
         <div class="to">
              <h4>Fly To The Moon</h4>
                  <div class="clearfix">
                       <div class="the">
                            <h4>**Wow**</h4>
                       </div>
                       <div class="moon">
                            <h4>**Great**</h4>                      
                       </div>
                   </div>
          </div>
</div>
你问:

  

如何从data-original获取<img class="aye">值,并从<h4>代码中获取值“哇”和“好”?

使用XPath,您可以直接获取字符串值:

string(//div[@class='fly']/img/@data-original)

这是所有div中img标签的第一个data-original属性的字符串,其中class =“fly”。

string(//div[@class='fly']//h4[not(following-sibling::*//h4)][1])
string(//div[@class='fly']//h4[not(following-sibling::*//h4)][2])

这些是第一个和第二个<h4>标记的字符串值,并非由所有div <h4>中的另一个class="fly"标记自行跟踪。

这看起来有点像现在的方式,但是通过迭代,不再需要前面的那些部分,因为xpath将是相对的:

//div[@class='fly']
    string(./img/@data-original)
    string(.//h4[not(following-sibling::*//h4)][1])
    string(.//h4[not(following-sibling::*//h4)][2])

要在PHP中使用xpath string(...)表达式,您必须使用DOMXPath::evaluate()而不是DOMXPath::query()。这将如下所示:

$aye  = $xpath->evaluate("string(//div[@class='fly']/img/@data-original)");
$h4_1 = $xpath->evaluate("string(//div[@class='fly']//h4[not(following-sibling::*//h4)][1])");
$h4_2 = $xpath->evaluate("string(//div[@class='fly']//h4[not(following-sibling::*//h4)][2])");

迭代和输出的完整示例:

// all <div> tags with class="fly"
$divs = $xpath->evaluate("//div[@class='fly']");

foreach ($divs as $div) {

    // the first data-original attribute of an <img> inside $div
    echo $xpath->evaluate("string(./img/@data-original)", $div), "<br/>\n";

    // all <h4> tags anywhere inside the $div
    $h4s = $xpath->evaluate('.//h4[not(following-sibling::*//h4)]', $div);

    foreach ($h4s as $h4) {
        echo $h4->nodeValue, "<br/>\n";
    }
}

如示例所示,您也可以将评估也用于节点列表。不再使用<h4>获取所有string()代码中的值,因为我认为可能只有两个以上。

Online Demo including special string output (just exemplary)

echo <<<HTML
{$xpath->evaluate("string(//div[@class='fly']/img/@data-original)")}<br/>
    {$xpath->evaluate("string(//div[@class='fly']//h4[not(following-sibling::*//h4)][1])")}<br/>
    {$xpath->evaluate("string(//div[@class='fly']//h4[not(following-sibling::*//h4)][2])")}<br/>
<hr/>
HTML;