DOMXPATH->没有获得div的第一个元素

时间:2013-03-18 04:06:06

标签: php xpath microdata schema.org domxpath

我正在使用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

}

2 个答案:

答案 0 :(得分:1)

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

  1. 返回匹配div的列表
  2. 打印每个div的所有内容,但不包含包含div的内容
  3. 以下演示了这种方法:

    $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。

答案 1 :(得分:0)

您要找的microdata包含itempropitemscopeitemtypecontent属性。

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

基于libxml的PHP XML扩展中的解析不能单独使用xpath,因为该库仅支持xpath 1.0,并且您无法使用该xpath版本执行所有操作。特别是在这种情况下,只选择具有相对于不包含具有该特定属性的子项的上下文节点的特定属性的descendant-or-self 。所以总是需要一些包装代码。如果您有兴趣了解更多相关内容,我发现以下问题绕过类似的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 Microdata class as gist