Как найти только прямых потомков с помощью 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 - ваш элемент верхнего уровня)

Другие вопросы по тегам