2013-05-24 16 views
16

Có cách nào để thực hiện truy vấn xpath trên DOMNode không? Hoặc ít nhất là chuyển đổi nó thành DOMXPath?Làm cách nào để thực hiện truy vấn XPath trên DOMNode?

<html> 
    ... 
    <div id="content"> 
    ... 
    <div class="listing"> 
     ... 
     <div></div> 
     <div></div> 
     <div class='foo'> 
      <h3>Get me 1</h3> 
      <a>and me too 1</a> 
     </div> 
    </div> 
    <div class="listing"> 
     ... 
     <div></div> 
     <div></div> 
     <div class='foo'> 
      <h3>Get me 2</h3> 
      <a>and me too 1</a> 
     </div> 
    </div> 
    .... 
    </div> 
</html> 

Đây là mã của tôi. Tôi đang cố gắng để có được một danh sách các mảng có giá trị của h3 và một thẻ trong mỗi mảng. Để thực hiện điều đó, tôi cần có được mỗi danh sách và sau đó nhận giá trị h3 và thẻ trong mỗi danh sách.

$html_dom = new DOMDocument(); 
@$html_dom->loadHTML($html); 
$x_path = new DOMXPath($html_dom); 

$nodes= $x_path->query("//div[@id='content']//div[@class='listing']"); 

foreach ($nodes as $node) 
{ 
    // I want to further dig down here using query on a DOMNode 
} 
+0

trong khi có thể truy vấn từ một nút cụ thể, bạn chỉ có thể truy vấn tất cả các div với lớp foo. Hoặc con div cuối cùng của danh sách và nhận được các giá trị ngay lập tức. – Gordon

+0

Tôi đã suy nghĩ về việc nhận được danh sách đầu tiên và sau đó truy vấn các giá trị bên trong nó để tôi có thể đặt nó dễ dàng trong một mảng trong cấu trúc đó. Nhưng tôi đoán tôi có thể chỉ phù hợp với các chỉ số của các kết quả của h3 và nếu tôi muốn. – arvinsim

Trả lời

26

Vượt qua nút như là đối số thứ hai để DOMXPath::query

contextnode: Các contextnode tùy chọn có thể được chỉ định cho làm các truy vấn XPath tương đối. Theo mặc định, các truy vấn liên quan đến phần tử gốc.

Ví dụ:

foreach ($nodes as $node) { 
    foreach ($x_path->query('h3|a', $node) as $child) { 
     echo $child->nodeValue, PHP_EOL; 
    } 
} 

này sử dụng UNION operator cho một kết quả của

Get me 1 
and me too 1 
Get me 2 
and me too 1 

Nếu bạn không cần bất kỳ truy vấn phức tạp, bạn cũng có thể làm

foreach ($nodes as $node) { 
    foreach ($node->getElementsByTagName('a') as $a) { 
     echo $a->nodeValue, PHP_EOL; 
    } 
} 

Hoặc thậm chí bằng cách lặp lại các nút con (lưu ý rằng i này ncludes tất cả các nút văn bản)

foreach ($nodes as $node) { 
    foreach ($node->childNodes as $child) { 
     echo $child->nodeName, PHP_EOL; 
    } 
} 

Tuy nhiên, tất cả điều đó là không cần thiết vì bạn có thể lấy các nút trực tiếp:

$nodes= $x_path->query("/html/body//div[@class='listing']/div[last()]"); 

foreach ($nodes as $i => $node) { 
    echo $i, $node->nodeValue, PHP_EOL; 
} 

sẽ cung cấp cho bạn hai nút trong div con cuối cùng của tất cả các divs với một giá trị thuộc tính lớp niêm yết và đầu ra các giá trị nút văn bản kết hợp, bao gồm khoảng trắng

0 
      Get me 1 
      and me too 1 

1 
      Get me 2 
      and me too 1 

Tương tự như vậy, sau đây

"//div[@class='listing']/div[last()]/node()[name() = 'h3' or name() = 'a']" 

sẽ cung cấp cho bạn H3 Bốn đứa trẻ và các nút A và đầu ra

0Get me 1 
1and me too 1 
2Get me 2 
3and me too 1 

Nếu bạn cần phải phân biệt những bằng tên trong khi iterating qua chúng, bạn có thể làm

foreach ($nodes as $i => $node) { 
    echo $i, $node->nodeName, $node->nodeValue, PHP_EOL; 
} 

mà sau đó sẽ tặng

0h3Get me 1 
1aand me too 1 
2h3Get me 2 
3aand me too 1 
+0

điều gì sẽ xảy ra nếu anh ta muốn lưu trữ h3 và một biến khác nhau như sau: http://stackoverflow.com/questions/43131400/xpath-query-get-child-nodes-in-a-parent-node-using-a- vòng lặp – DragonFire

5

Cung cấp $node làm nút bối cảnh.

foreach ($nodes as $node) 
{ 
    $morenodes = $x_path->query(".//h3", $node); 
} 

Xem $contextnode trong cuốn hướng dẫn: http://php.net/manual/en/domxpath.query.php

+0

Khi tôi đã làm giải pháp đó, tôi dường như nhận được kết quả tương tự khi loooping qua nodelist ... Tôi tiếp tục nhận được các giá trị cho danh sách đầu tiên – arvinsim

+0

truy vấn xpath bạn đang sử dụng là gì? Chỉnh sửa: Bên trong vòng lặp đó. – EPB

+3

Tôi đã đi trước và chỉnh sửa với một truy vấn ví dụ tôi đã sử dụng ban đầu để kiểm tra câu trả lời của tôi. Bắt đầu với '.' là quan trọng nếu bạn định sử dụng' // 'để bắt đầu truy vấn, mà dường như luôn luôn liên quan đến root. – EPB

1

Chỉ cần hoàn thành, có DOMNode::getNodePath phương thức trả về xpath của nút đó.Vì vậy, bạn cũng có thể sử dụng $x_path->query($node->getNodePath().'//h3')