卡在一个兔子洞中,试图解析HTML文件。
基本知识:
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTMLFile('myfile.html');
$xp = new DOMXPath($dom);
初始化之后,我的技术一直是使用XPATH查询来获取所需的变量。
我真的没有问题,如果有一个特定的项目或节点,很容易查明和检索。
因此,在我加载的HTML中,它基本上是循环形成的。缩小后看起来像这样:
<div class="intro">
<div class="desc-wrap">
Text Text Text
</div>
<div class="main-wrap">
<table class="table-wrap">
<tbody>
<tr>
<th class="range">Range </th>
<th>#1</th>
<th>#2</th>
</tr>
</tbody>
</table>
</div>
</div>
<div class="intro">
<div class="desc-wrap">
Text Text Text
</div>
<div class="main-wrap">
<table class="table-wrap">
<tbody>
<tr>
<th class="range">Range </th>
<th>#1</th>
<th>#2</th>
<th>#3</th>
<th>#4</th>
</tr>
</tbody>
</table>
</div>
</div>
此操作持续100次(表示<div class="intro"> . . . </div>
的100个实例
因此,我正在尝试获取desc-wrap
的内容(那里没有问题),文本节点以及每个表中有多少<th>
个计数。
我查询div可能是一个XPath查询可能比两个查询好。
$intropath = $xp->query("//div[@class='intro']");
圈起来。
$f=1;
foreach ($intropath as $sp) {
echo $f++ . '<br />'; // Makes it way to 100, good.
我遇到的问题/核心问题是试图计算每个表中<th>
的数量。
$gettables = $xp->query("//div[contains(@class,'main-wrap')]/table[contains(@class, 'table-wrap')]//th", $sp);
var_dump($getsizes); // public 'length' => int 488
// Okay, so this is getting all the <th> elements in the
// entire document, not just in the loop. Maybe not what I want.
这是我尝试过的其他方法(我的意思是失败了)
好吧,让我们尝试仅定位第一个表(在[0]
之前添加//th
),看看是否可以得到一些东西。
$gettables = $xp->query("//div[contains(@class,'main-wrap')]/table[contains(@class, 'table-wrap')][0]//th", $sp);
不。非对象。长度为0。不知道为什么。好吧,让我们开始吧。
也许尝试一下?
//div[contains(@class,'main-wrap')]/table[contains(@class, 'table-wrap')]//th[count(following-sibling::*)]
好的。因此,Length =100。必须得到一个th
并进行推断。不是我想要的。
也许只是
//th[count(*)]
不。非对象。
也许是吗?
count(//div[contains(@class,'main-wrap')]/table[contains(@class, 'table-wrap')]//th)
不。更多非对象。
这可能是我尝试过的例子。
失败(很好,学习)很有趣,但是我想念的是什么?
我的输出...我只想找出每个表中有多少<th>
个。
所以,就像:
foreach ($intropath as $sp) {
$xpath = $xp->query("//actual/working/xpath/for/individual/th");
$thcount = count($getsizes->item(0)); // or something?
echo $thcount . '<br>';
在上面的示例中,将输出
3
5
,当然还要继续进行其他98次迭代。
这可能很愚蠢。我一直在引用这个cheatsheet和这个cheatsheet,并且我已经学到了很多有关XPATH功能的知识,但是这个答案在暗示我。此时,我什至不确定foreach ($intropath as $sp) {
甚至是否是实现我正在做的事情的正确方法。
有人想把我从这个洞里挖出来,让我继续下一步和/或我的生活吗?
答案 0 :(得分:1)
使用迭代的query()
调用计数合格节点。
代码:(Demo)
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($html);
$xp = new DOMXPath($dom);
foreach ($xp->query("//div[contains(@class,'main-wrap')]/table[contains(@class, 'table-wrap')]//tr") as $node) {
echo $xp->query("th", $node)->length , "\n";
}
输出:
3
5
答案 1 :(得分:0)
首先,查询table
:
$intropath = $xp->xpath("//table[contains(@class, 'table-wrap')]");
然后通过另一个XPath查询获得th
的计数,每个table
的计数和count
PHP函数应用于相对于上下文节点的所有th
的计数:< / p>
foreach ($intropath as $tab) {
$count = count($tab->xpath(".//th"));
echo $count . "<br>";
}
这应该是全部。
PS:
显然,PHP不喜欢XPath count
函数,因此我改用了PHP count
函数。
仅出于完整性考虑:
如果可以使用XPath-2.0,则以下表达式将更紧凑:
string-join(//table[contains(@class, 'table-wrap')]/count(.//th),'#')
在这里,#
是每个table
计数之间的分隔符。