Perl 按第一个子元素的名称选择HTML元素
如果所有Perl 按第一个子元素的名称选择HTML元素,perl,Perl,如果所有元素都有子元素,那么我需要找到id属性的值 例如,给定以下HTML <div id="a1"> <span> xa1 </span> </div> <div id="a2"> <p>...</p> <span> xa2 </span> </div> <div id="a3">
元素都有
子元素,那么我需要找到id
属性的值
例如,给定以下HTML
<div id="a1"> <span> xa1 </span> </div>
<div id="a2"> <p>...</p> <span> xa2 </span> </div>
<div id="a3"> <p> <span> xa3 </span> </p> </div>
<div id="a4"> <p>...</p> </div>
<div id="b1"> </div> <span> xb1 </span>
<div id="b2"> </div> <p> <span> xb1 </span> </p>
<div id="b3"> </div> <p>.</p> <span> xb3 </span>
不幸的是,
Mojo::DOM
不支持XPath表达式和CSS,因为前者是非常自然的表达式
<>你可能想考虑切换到。代码如下所示。它使用XPath表达式
//div[*][local-name(*[1])="span"]/@id
它要求文档中至少有一个子元素且第一个子元素的本地名称为span
的任何div
元素的id
属性
use strict;
use warnings;
use 5.014;
use HTML::TreeBuilder::XPath;
my $tree = do {
local $/;
HTML::TreeBuilder::XPath->new_from_content(<DATA>);
};
say for $tree->findvalues('//div[*][local-name(*[1])="span"]/@id');
__DATA__
<html><body>
<div id="a1"> <span> xa1 </span> </div>
<div id="a2"> <p>...</p> <span> xa2 </span> </div>
<div id="a3"> <p> <span> xa3 </span> </p> </div>
<div id="a4"> <p>...</p> </div>
<div id="b1"> </div> <span> xb1 </span>
<div id="b2"> </div> <p> <span> xb1 </span> </p>
<div id="b3"> </div> <p>.</p> <span> xb3 </span>
<p id="p1"> <span> xp1 </span> </p>
<p id="p2"> <p>...</p> <span> xp2 </span> </p>
<p id="p3"> <p> <span> xp3 </span> </p> </p>
<p id="p4"> <p>...</p> </p>
</body></html>
您可以使用css样式选择器和Mojo::DOM的方法以稍微迂回的方式获得所需的元素: 或者,如果您知道这只是您想要的第一个这样的div,那么下面的方法就可以了:
say "id: " . $dom->at('div > span:first-child')->parent->attr('id');
或者:
my @spans = $div->find('div > span:first-child')->each;
say $div->attr('id') if (@spans == 1);
或者这个:
my @kids = $div->children;
say $div->attr('id') if @kids and $kids[0]->type eq 'span';
Thanx,但它也会打印
a1
和a2
。正如我在问题中所说,我只想要a1
。@cajwine:我道歉。我只是在重读问题时遇到了这个问题。我更喜欢Mojo::DOM,因为它更接近jquery,所以我不需要再学习另一种格式。@marneborn:这很公平。实际上是在CSS和XPath之间进行选择,因为CSS3的选择主要是个人偏好,但最好在Mojo::DOM
YES中包含这两种选择!我有点忽略了第一个孩子和第n个孩子。。塔克斯。接受这一点,因为这是我已经知道的Mojo::DOM解决方案。
id: a1
say "id: " . $dom->at('div > span:first-child')->parent->attr('id');
my @spans = $div->find('div > span:first-child')->each;
say $div->attr('id') if (@spans == 1);
my @kids = $div->children;
say $div->attr('id') if @kids and $kids[0]->type eq 'span';