2012-12-18 39 views
3

我想通過外部網站的HTML排序,不幸的是,該網站組織得很差。該數據可能是這個樣子:獲取DOMXpath結果低於以前的結果在HTML

<a class="title">Title One</a> 
<a class="item">Item One</a> 
<a class="item">Item Two</a> 

<a class="title">Title Two</a> 
<a class="item">Item One</a> 
<a class="item">Item Two</a>  

我正與XPath查詢喜歡本作的標題工作:

$titles = $x->evaluate('//a[@class="title"]'); 

現在,我想與它們下面的項目清單標題。不幸的是,這些元素沒有一個方便地包裝在父級div中,所以我不能僅僅通過父級中的所有內容進行篩選。所以,我用這樣的查詢項目:

$titles = $x->evaluate('//a[@class="item"]'); 

理想的情況下,想什麼,我做的是隻檢查當前標題元素下面的結果。因此,如果我循環播放並擊中「標題一」,我只想檢查顯示在標題一和標題二之間的「項目」結果。有沒有辦法做到這一點?

修改HTML不是一個選項。我知道這個問題有點荒謬,我的解釋可能會很糟糕,但如果有解決方案,那真的會對我有所幫助!

謝謝大家。

回答

1

你可以先找到標題元素,然後用->nextSibling()前進:

$html =<<<EOM 
<a class="title">Title One</a> 
<a class="item">Item One</a> 
<a class="item">Item Two</a> 

<a class="title">Title Two</a> 
<a class="item">Item One</a> 
<a class="item">Item Two</a> 
EOM; 

$d = new DOMDocument; 
$d->loadHTML($html); 
$x = new DOMXPath($d); 
foreach ($x->query('//a[@class="title"]') as $node) { 
    echo "Title: {$node->nodeValue}\n"; 
    // iterate the siblings 
    while ($node = $node->nextSibling) { 
     if ($node->nodeType != XML_ELEMENT_NODE) { 
      continue; // skip text nodes 
     } 
     if ($node->getAttribute('class') != 'item') { 
      // no more .item 
      break; 
     } 
     echo "Item: {$node->nodeValue}\n"; 
    } 
} 

輸出:

Title: Title One 
Item: Item One 
Item: Item Two 
Title: Title Two 
Item: Item One 
Item: Item Two 
+0

非常感謝,這真棒! – GhostCode

+1

這不是xpath;) – hakre

0

您要選擇的<a>元素的所有後面的兄弟姐妹與class="title"這又是<a>元素,但與class="item",並且有第一個前面的兄弟<a>元素與class="title"是你開始看起來確切的第一個元素。

E.g.在XPath中,例如,你要尋找的第一title元素:

//a[class="title"][1] 

該元素的item要素如下:

//a[@class="title"][1] 
    /following-sibling::a[ 
     @class="item" 
     and preceding-sibling::a[@class="title"][1] 
      = //a[@class="title"][1] 
    ] 

如果你想使用的,在代碼中,

$titles = $xp->query('//a[@class="title"]'); 
foreach ($titles as $title) 
{ 
    echo $title->nodeValue, ":\n"; 
    $query = './following-sibling::a[@class="item" and 
       preceding-sibling::a[@class="title"][1] = ' . 
       $title->getNodePath() . ']'; 
    foreach ($xp->query($query, $title) as $item) 
    { 
     echo ' * ', $item->nodeValue, "\n"; 
    }  
} 

輸出::

01可以通過創建一個相對錶達於標題組件和使用 DOMelement::getNodePath()這樣做
Title One: 
* Item One 
* Item Two 
Title Two: 
* Item Three 
* Item Four 
+0

演示:http://eval.in/4899 – hakre