Как найти только прямых потомков с помощью HTML::TreeBuilder?
Предположим, у меня есть HTML-дерево вроде этого:
div
`- ul
`- li (*)
`- li (*)
`- li (*)
`- li (*)
`- ul
`- li
`- li
`- li
Как выбрать <li>
элементы, отмеченные (*)
? Они прямые потомки первого <ul>
элемент.
Вот как я нахожу первый <ul>
элемент:
my $ul = $div->look_down(_tag => 'ul');
Теперь у меня есть $ul
, но когда я делаю такие вещи, как:
my @li_elements = $ul->look_down(_tag => 'li');
Также находит <li>
элементы, которые погружены глубже в дерево HTML.
Как мне найти только <li>
элементы, которые являются прямыми потомками первого <ul>
элемент? У меня их неизвестное количество. (Я не могу просто выбрать первые 4, как в примере).
3 ответа
Вы можете получить все дети HTML::Element
объект с помощью content_list
метод, поэтому все дочерние узлы первого <ul>
элемент в документе будет
use HTML::TreeBuilder;
my $tree = HTML::TreeBuilder->new_from_file('my.html');
my @items = $tree->look_down(_tag => 'ul')->content_list;
Но это гораздо более выразительно, чтобы использовать HTML::TreeBuilder::XPath
, который позволяет вам найти все <li>
дети <ul>
дети <div>
элементы в любом месте документа, как это
use HTML::TreeBuilder::XPath;
my $tree = HTML::TreeBuilder->new_from_file('my.html');
my @items = $tree->findnodes('//div/ul/li')->get_nodelist;
Если вы хотите использовать метод look_down, вы можете добавить дополнительные критерии, чтобы получить только дочерние элементы:
my @li_elements = $ul->look_down(_tag => 'li', sub {$_[0]->parent() == $ul});
Чтобы сделать эту страницу идеально завершенной, я добавлю еще одну опцию:
@li = grep { $_->tag() eq 'li' } $ul->content_list;
(Где $ul - ваш элемент верхнего уровня)