【问题标题】:PHP XPath substring-after only returning first resultPHP XPath substring-after 只返回第一个结果
【发布时间】:2011-09-18 10:07:35
【问题描述】:

我正在做一些 HTML 抓取,但这个查询碰了壁。我正在尝试从以下 HTML 页面结构返回一组值:

<div id="product-grid">
    <ul>
        <li><div class="price">Cash Price: $20.00</div></li>
        <li><div class="price">Cash Price: $30.00</div></li>
        <li><div class="price">Cash Price: $40.00</div></li>
    </ul>
</div>

我正在尝试在列表中返回 "$20.00" 价格。如果我使用以下 XPath:

id('product-grid')//p[@class="price"] 

我得到所有“现金价格:40.00 美元”的结果列表。如果我尝试以下查询:

substring-after(id('product-grid')//p[@class="price"] , "Price: ")

我得到了正确的输出,但只得到了第一个结果。有谁知道我怎样才能得到所有结果?

我正在为XPath 运行PHP5.3.3libxml 2.7.8。我按如下方式调用 xpath:

$xpath = new DOMXPath( $html ); 
$resultset= $xpath->query($query);

我一直在疯狂地搜索,试图找出为什么会发生这种情况!请帮忙!

【问题讨论】:

    标签: php xml xpath


    【解决方案1】:

    抱歉,我认为这不可能一步到位。据我所知,XPath 1.0 不支持 XPath 路径末尾的函数调用。答案here表示相同。

    此外,您不能使用id('product-grid') 作为第一个路径部分,因为 id 在根元素上,不需要专门选择。如果您的示例 XML 只是较大 XML 文档的一个片段,那么 id() 可能是必要的。

    以下按预期工作:

    $xml = new DOMDocument();
    $xml->loadXML('<div id="product-grid">
     <ul>
      <li><div class="price">Cash Price: $20.00</div></li>
      <li><div class="price">Cash Price: $30.00</div></li>
      <li><div class="price">Cash Price: $40.00</div></li>
    </ul>
    </div>');
    $xpath = new DOMXPath($xml);
    foreach ($xpath->query('//div[@class="price"]') as $n) {
        var_dump(substr($n->nodeValue, strpos($n->nodeValue, '$')));
    }   
    

    【讨论】:

      【解决方案2】:

      获取列表后必须使用子字符串。

       id('product-grid')//div[@class="price"][substring-after(., 'Price: ')]
      

      这应该可行。

      编辑:这似乎有效。但是我无法测试返回值,因为我不知道如何获取子字符串的值。你用什么?

      【讨论】:

      • 在轴上使用函数是 XPath 2.0 的特性。可能在标准 PHP 环境中不可用。您应该能够将其应用于谓词过滤器:id('product-grid')//p[@class="price"][substring-after(., 'Price: ')]. Also, the sample XML shows div` 元素与 @class,但示例 XPath(和您的答案)期望 p 具有 @class
      • @Mads Hansen,经过编辑以符合 1.0。我使用了 OP 的代码,所以我使用了 p。确实将其更改为 div。
      【解决方案3】:

      所需的处理不能只指定为单个 XPath 1.0 表达式,因为根据定义,任何需要单个字符串参数但给定节点集的函数都会采用第一个字符串值此节点集的唯一(按文档顺序)节点。

      此外,与 XPath 1.0 中的 XPath 2.0 不同,它不允许将函数调用指定为位置步骤。

      因此,一种解决方案是发出此 XPath 表达式

      substring-after((id('product-grid')//p[@class="price"])[$k], "Price: ") 
      

      N 次,将每个表达式中的 $k 替换为 1,2,..., N,其中 N 是对另一个 XPath 表达式求值的结果:

      count(id('product-grid')//p[@class="price"])
      

      使用 XPath 2.0 可以通过这个简单且单一的表达式完成此操作

      id('product-grid')//p[@class="price"]/substring-after(., "Price: ")
      

      在评估时会产生所需的字符串序列。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-26
        • 2014-04-17
        • 2016-05-23
        • 1970-01-01
        • 2017-01-03
        • 1970-01-01
        相关资源
        最近更新 更多