Using Perl XML::Twig, how can I loop on each sibling until reaching the last node ?
while (condition_sibling_TWIG, $v)
{
$v=$v->next_sibling;
$v->print;
# process $v
}
Should the condition be ($v != undef) ?
thanks
Using Perl XML::Twig, how can I loop on each sibling until reaching the last node ?
while (condition_sibling_TWIG, $v)
{
$v=$v->next_sibling;
$v->print;
# process $v
}
Should the condition be ($v != undef) ?
thanks
You can use next_siblings
to get the list of siblings:
foreach my $sibling ($elt->next_siblings)
{ # process sibling
}
next_siblings
accepts an optional condition as argument, which is an XPath step, or at least the subset of XPath supported by XML::Twig: $elt->next_siblings('p[@type="secret"]'))
Update:
The sibling
method returns the next sibling or undef if no siblings are left. You can use it to fetch the next one until there are none left.
sibling ($offset, $optional_condition)
Return the next or previous $offset-th sibling of the element, or the $offset-th one matching $optional_condition. If $offset is
negative then a previous sibling is returned, if $offset is positive then a next sibling is returned. $offset=0 returns the element if there is no condition or if the element matches the condition>, undef otherwise.
Here's an example:
use strict; use warnings;
use XML::Twig;
my $t= XML::Twig->new();
$t->parse(<<__XML__
<root>
<stuff>
<entry1></entry1>
<entry2></entry2>
<entry3></entry3>
<entry4></entry4>
<entry5></entry5>
</stuff>
</root>
__XML__
);
my $root = $t->root;
my $entry = $root->first_child('stuff')->first_child('entry1');
while ($entry = $entry->sibling(1)) {
say $entry->print . ' (' . $entry->path . ')';
}
This only gives you the ones that come after the element you already have. If you start at entry 3 you will only get entries 4 and 5.
Original (edited) answer:
You can also use the siblings
method to iterate over a list of all siblings of an element.
siblings ($optional_condition)
Return the list of siblings (optionally matching $optional_condition) of the element (excluding the element itself).
The elements are ordered in document order.
Replace the code from above with this:
my $root = $t->root;
my $entry1 = $root->first_child('stuff')->first_child('entry1');
# This is going to give us entries 2 to 5
foreach my $sibling ($entry1->siblings) {
say $sibling->print . ' (' . $sibling->path . ')';
}
This gives you all siblings of your starting element, but not that one itself. If you start at entry3
you will get entries 1, 2, 4 and 5.