【问题标题】:How do I do an XPath query on a DOMNode?如何在 DOMNode 上执行 XPath 查询?
【发布时间】:2013-05-19 14:33:56
【问题描述】:

有没有办法在 DOMNode 上进行 xpath 查询?或者至少将其转换为 DOMXPath?

<html>
  ...
  <div id="content">
     ...
     <div class="listing">
         ...
         <div></div>
         <div></div>
         <div  class='foo'>
           <h3>Get me 1</h3>
           <a>and me too 1</a>
         </div>
     </div>
     <div class="listing">
         ...
         <div></div>
         <div></div>
         <div class='foo'>
           <h3>Get me 2</h3>
           <a>and me too 1</a>
         </div>
     </div>
     ....
  </div>
</html>

这是我的代码。我正在尝试获取一个数组列表,其中包含 h3 的值和每个数组中的标签。为此,我需要获取每个列表,然后在每个列表中获取 h3 和标签的值。

$html_dom = new DOMDocument();
@$html_dom->loadHTML($html);
$x_path = new DOMXPath($html_dom);

$nodes= $x_path->query("//div[@id='content']//div[@class='listing']");

foreach ($nodes as $node)
{
  // I want to further dig down here using query on a DOMNode
}

【问题讨论】:

  • 虽然可以从特定节点进行查询,但您可以简单地查询所有具有类 foo 的 div。或列表的最后一个 div 子项并立即获取值。
  • 我想先获取列表,然后查询其中的值,以便我可以轻松地将其放入该结构中的数组中。但我想我可以匹配 h3 和 a 的结果索引,如果我愿意的话。

标签: php dom


【解决方案1】:

提供您的$node 作为上下文节点。

foreach ($nodes as $node)
{
   $morenodes = $x_path->query(".//h3", $node);
}

参见手册中的$contextnodehttp://php.net/manual/en/domxpath.query.php

【讨论】:

  • 当我做那个解决方案时,我似乎在循环节点列表时得到了相同的结果......我不断获得第一个列表的值
  • 您使用的 xpath 查询是什么?编辑:在循环内部。
  • 我继续编辑了一个示例查询,我最初用于测试我的答案。如果您打算使用// 来启动查询,那么从. 开始很重要,这显然总是相对于root。
【解决方案2】:

将节点作为第二个参数传递给DOMXPath::query

contextnode:可以指定可选的 contextnode 来进行相对 XPath 查询。默认情况下,查询是相对于根元素的。

例子:

foreach ($nodes as $node) {
    foreach ($x_path->query('h3|a', $node) as $child) {
        echo $child->nodeValue, PHP_EOL;
    }
}

这使用UNION operator 作为结果

Get me 1
and me too 1
Get me 2
and me too 1

如果你不需要任何复杂的查询,你也可以这样做

foreach ($nodes as $node) {
    foreach ($node->getElementsByTagName('a') as $a) {
      echo $a->nodeValue, PHP_EOL;
    }
}

或者甚至通过迭代子节点(注意这包括所有的文本节点)

foreach ($nodes as $node) {
    foreach ($node->childNodes as $child) {
      echo $child->nodeName, PHP_EOL;
    }
}

但是,所有这些都是不需要的,因为您可以直接获取这些节点:

$nodes= $x_path->query("/html/body//div[@class='listing']/div[last()]");

foreach ($nodes as $i => $node) {
    echo $i, $node->nodeValue, PHP_EOL;
}

将在所有 div 的最后一个 div 子节点中为您提供两个节点,其 class 属性值为 list 并输出组合的文本节点值,包括空格

0
           Get me 1
           and me too 1

1
           Get me 2
           and me too 1

同样,以下

"//div[@class='listing']/div[last()]/node()[name() = 'h3' or name() = 'a']"

会给你四个子 H3 和 A 节点和输出

0Get me 1
1and me too 1
2Get me 2
3and me too 1

如果您需要在迭代它们时按名称区分它们,您可以这样做

foreach ($nodes as $i => $node) {
    echo $i, $node->nodeName, $node->nodeValue, PHP_EOL;
}

然后会给出

0h3Get me 1
1aand me too 1
2h3Get me 2
3aand me too 1

【讨论】:

【解决方案3】:

为了使它完整,有一个 DOMNode::getNodePath 方法返回该节点的 xpath。所以你也可以使用$x_path-&gt;query($node-&gt;getNodePath().'//h3')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多