簡體   English   中英

獲取DOMXpath結果低於HTML中的上一個結果

[英]Get DOMXpath results below previous result in HTML

我正在嘗試對外部網站的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。 我知道這個問題有點荒謬,我的解釋可能很糟糕,但是如果有解決辦法的話,那真的會對我有所幫助!

感謝大家。

您可以先找到title元素,然后使用->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

你想選擇<a>元素的所有以下兄弟,其中class="title"再次是<a>元素但是帶有class="item"並且具有第一個前面的兄弟<a>元素,帶有class="title"是你開始看的確切的第一個元素。

例如在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]
    ]

如果要在代碼中使用它,可以通過創建title元素的相對表達式並使用DOMelement::getNodePath()

$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";
    }    
}

輸出:

Title One:
 * Item One
 * Item Two
Title Two:
 * Item Three
 * Item Four

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM