我有这样的HTML
<h1>My heading</h1>
<p class="class1">
<strong>SOMETHING</strong> INTERESTING (maybe not).
</p>
<div class="mydiv">
<p class="class2">
<a href="http://www.link.com">interesting link</a> </p>
<h2>Some other heading</h2>
Run Code Online (Sandbox Code Playgroud)
h1和h2之间的内容各不相同 - 我知道我可以在Mojo :: Dom中使用css选择器,比如选择h1或h2或p标签的内容 - 但是如何选择h1和h2之间的所有内容?或者更一般地说,任何两个给定标签集之间的所有内容?
这很简单.您可以只选择Mojo :: Collection对象中的所有有趣元素(这是Mojo :: DOM的children方法所做的),并在迭代该集合时执行某种状态机匹配.
是在标量上下文中使用Perl的范围运算符..:
在标量上下文中,".."返回一个布尔值.运算符是双稳态的,就像一个触发器,并模拟sed,awk和各种编辑器的行范围(逗号)运算符.每个".."运算符都保持自己的布尔状态,甚至在调用包含它的子例程时也是如此.只要其左操作数为假,它就是假的.一旦左操作数为真,范围运算符将保持为真,直到右操作数为真,此后范围运算符再次变为假.在下次评估范围运算符之前,它不会变为假.
这是一个
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
use Mojo::DOM;
# slurp all DATA lines
my $dom = Mojo::DOM->new(do { local $/; <DATA> });
# select all children of <div id="yay"> into a Mojo::Collection
my $yay = $dom->at('#yay')->children;
# select interesting ('..' operator in scalar context: flip-flop)
my $interesting = $yay->grep(sub { my $e = shift;
$e->type eq 'h1' .. $e->type eq 'h2';
});
say $interesting->join("\n");
__DATA__
<div id="yay">
<span>This isn't interesting</span>
<h1>INTERESTING STARTS HERE</h1>
<strong>SOMETHING INTERESTING</strong>
<span>INTERESTING TOO</span>
<h2>END OF INTERESTING</h2>
<span>This isn't interesting</span>
</div>
Run Code Online (Sandbox Code Playgroud)
<h1>INTERESTING STARTS HERE</h1>
<strong>SOMETHING INTERESTING</strong>
<span>INTERESTING TOO</span>
<h2>END OF INTERESTING</h2>
Run Code Online (Sandbox Code Playgroud)
所以我使用Mojo :: Collection grep来过滤集合对象$yay.因为它查找真值,所以它为给定函数的返回值创建了一个标量上下文,因此..操作符就像一个触发器.它在第一次看到一个h1元素后变为真实,并在它第一次看到一个元素后变为假h2,所以你得到了包括它们在内的所有标题之间的所有界限.
因为我认为你知道一些Perl,你可以一起使用任意测试,..我希望这有助于解决你的问题!