Q:

How to select siblings (xpath syntax) with Perl's XML::Twig?

I need to select the next node via next_sibling or first_elt. But I want to filter by node name (containing the string "TON")
first_elt ('HILTON[@method]' or 'SHERATON[@method]');

or 
next_sibling ('HILTON[@method]' or 'SHERATON[@method]');

or
next_sibling ('TON[@method]');

Example I tried (not working):
#!/usr/bin/perl -w
use warnings;
use XML::Twig;
$t-> parsefile ('file.xml');

my $Y0=$t->first_elt('HILTON[@method]' or 'SHERATON[@method]');

it will just process for 'HILTON[@method]'
my $Y0=$t->first_elt('/*TON[@method]');

wrong navigation condition '/*TON[@method]' () at C:/strawberry/perl/site/lib/XML/Twig.pm line 3523

A:

As this is outside of the XPath subset supported by XML::Twig, you have to use a custom filter, by passing code to first_elt:
$t->first_elt( sub {  $_[0]->tag=~ m{TON$} && $_[0]->att( 'method') })

This returns the first element for which the sub returns a true value.
The need for such an expression is a bit troubling though. In your example you define a class of elements by the fact that their name ends in TON. What happens when you have a CARLTON element? Or when MARRIOTT elements need to be processed with SHERATON and HILTON? Do you need to rewrite your queries?
If you are the one designing the format of the data, I would suggest revising the format. HILTON and SHERATON should probably be attributes of a HOTEL, BRAND or OWNER tag. Maybe an additional attribute would be useful, to mark that both types should be processed similarly. This attribute would only make sense if it is a property intrinsic to the data.
If the data is what it is and you have no input on its format, then I would have a list of the tags to process and check on these:
my %TAGS_TO_PROCESS= map { $_ => 1 } qw( HILTON SHERATON);
my $elt= $t->first_elt( sub {  $TAGS_TO_PROCESS{$_[0]->tag} && $_[0]->att( 'method') })

This way adding/substracting other tags is easy.

