3

外部 Web サイトの 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"]');

理想的には、私がやりたいことは、現在のタイトル要素の下の結果のみをチェックすることです。したがって、ループして「タイトル 1」を押した場合、タイトル 1 とタイトル 2 の間に表示される「アイテム」の結果のみを確認したいと考えています。これを行う方法はありますか?

HTML を変更することは、ここではオプションではありません。この質問は少しばかげており、私の説明はひどいものかもしれませんが、解決策があれば本当に助かります!

みんな、ありがとう。

4

2 に答える 2

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
于 2012-12-18T03:12:05.083 に答える
0

<a>要素の後続のすべての兄弟を選択する必要がありますがclass="title"、それらは再び<a>要素class="item"ですが、最初の前の兄弟<a>要素を持ち、最初class="title"に検索を開始する正確な要素です。

titleたとえば、xpath では、たとえば、最初の要素を探しています。

//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]
    ]

コードでそれを利用したい場合は、タイトル要素への相対式を作成し、次を使用してそれを行うことができます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
于 2012-12-18T03:24:22.170 に答える