我正在做一些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: ")
得到正确的输出,但只得到第一个结果。有人知道我怎么得到所有结果吗?
我运行PHP5.3.3
与libxml 2.7.8
的XPath
。我像这样调用xpath:
$xpath = new DOMXPath( $html );
$resultset= $xpath->query($query);
我一直在疯狂地搜索,试图找出为什么会发生这种情况!请帮助!
对不起,但我不认为这是可能的一步。据我所知,XPath 1.0不支持XPath路径末尾的函数调用。这里的答案表示相同。
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, '$')));
}
您必须在获得列表后使用子字符串
id('product-grid')//div[@class="price"][substring-after(., 'Price: ')]
应该可以。
EDIT:这似乎正在工作。然而,我不能测试返回值,因为我不知道如何获得子字符串的值。
所需的处理不能仅仅指定为单个XPath 1.0表达式,因为根据定义,任何期望单个字符串参数但给定一个节点集的函数,都取该节点集的第一个(按文档顺序)节点的字符串值。
另外,与XPath 2.0不同的是,XPath 1.0不允许将函数调用指定为定位步骤。
因此,一种解决方案是发出这个XPath表达式:substring-after((id('product-grid')//p[@class="price"])[$k], "Price: ")
N
次,用1,2,..., N
替换每个表达式中的$k
,其中N
是对另一个XPath表达式求值的结果:
count(id('product-grid')//p[@class="price"])
使用XPath 2.0可以使用这个简单的表达式:
id('product-grid')//p[@class="price"]/substring-after(., "Price: ")