0

我正在使用 DOMXPath 来获取特定节点的内容。对于我的问题,我想获取除嵌套 div 之外的匹配 div 的所有文本。

$html = 
'<div itemscope="itemscope" itemtype="http://schema.org/Event">
  <span itemprop="name"> Miami Heat at Philadelphia 76ers - Game 3 (Home Game 1)</span>
  <meta itemprop="startDate" content="2016-04-21">
    Thu, 04/21/16
    8:00 p.m    
  <div itemprop="offers" itemscope="itemscope" itemtype="http://schema.org/AggregateOffer">
    Priced from: <span itemprop="lowPrice">$35</span>
    <span itemprop="offerCount">1938</span> tickets left
  </div>
  <meta itemprop="endDate" content="2020-3-2"> end date of year    
  <div itemprop="attendee" itemscope="itemscope" itemtype="http://schema.org/Person">
     <span itemprop="name">Jane Doe</span>
     <meta itemprop="birthDate" content="1975-05-06"> 
    <div itemprop="sibling" itemscope="itemscope" itemtype="http://schema.org/Person">
        <span itemprop="name">Fatima Zohra</span>
        <meta itemprop="birthDate" content="1991-6-5">Jan 6
     </div>      
  </div>
</div>';

我首先尝试了以下方法,但这并没有返回嵌套的 div:

$tags = $xpath->query("//div[@itemscope='itemscope'][not(self::div)]/text()");

我目前的尝试如下,但不起作用:

$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$tags = $xpath->query('//div[not(ancestor::div)]');

foreach ($tags as $node) {
    echo $node->nodeValue; // body

}
4

2 回答 2

1

这个问题最好分成两部分:

  1. 返回匹配的 div 列表
  2. 打印每个 div 的所有内容,除了包含 div 的内容

下面演示了这种方法:

$dom = new DOMDocument;
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$divs = $xpath->query("//div[@itemscope='itemscope']");

foreach ($divs as $div) {
        $nodelist = $xpath->query('child::node()[not(self::div)][normalize-space()]',$div);

        foreach ($nodelist as $node) {
                echo $node->nodeValue . "\n";
        }
        echo "\n---------------------\n";
}

请注意以下事项:

  • 'child::node()' 而不是 '*' 包括文本节点
  • '[normalize-space()] 删除多余的空格,包括换行符

顺便说一句,'not(ancestor::div)' 明确表示不要返回嵌套在其他 div 中的 div。

于 2013-03-18T11:37:54.410 回答
0

您要查找的微数据itemprop带有、itemscope和属性itemtypecontent

所以您的问题实际上是关于如何从该 HMTL 文档中获取微数据。这基本上是 XML 解析的问题。由于 schema.org 微数据是(或多或少直截了当),我强烈建议使用 DOMDocument 加载 HMTL 文档,但使用 SimpleXML 来解析数据。

基于 libxml 的 PHP XML 扩展中的解析不能单独使用 xpath,因为该库仅支持 xpath 1.0,您无法使用该 xpath 版本完成所有操作。尤其是在这种情况下,仅选择具有特定属性的后代或自身,该特定属性相对于不包含具有该特定属性的子节点的上下文节点所以这总是需要一些包装代码。如果您有兴趣了解更多相关信息,我发现以下问题与您的类似 xpath 问题有关:

因此,将 xpath 代码包装在某个类中并立即访问感兴趣的数据:

$dom = new DOMDocument;
$dom->loadHTML($html);

$micro = new Micro($dom);
$event = $micro->Event;

foreach($event as $name => $value) {
    if ($value->isEmbed()) continue;
    printf("%s => %s\n", $name, $value);
}

给出以下输出:

name =>  Miami Heat at Philadelphia 76ers - Game 3 (Home Game 1)
startDate => 2016-04-21
endDate => 2020-3-2

或者您只需访问:

$micro->Event->name; # Miami Heat at Philadelphia 76ers - Game 3 (Home Game 1)

Micro数据类作为 gist

于 2013-03-20T01:50:42.107 回答