package XML::XPath::NodeSet;
$VERSION = '1.42';
use strict; use warnings;
use XML::XPath::Boolean;
use overload
'""' => \&to_literal,
'eq' => \&string_value,
'ne' => \&string_value,
'lt' => \&string_value,
'le' => \&string_value,
'gt' => \&string_value,
'ge' => \&string_value,
'bool' => \&to_boolean,
'==' => \&to_number,
'!=' => \&to_number,
'>' => \&to_number,
'<' => \&to_number,
'>=' => \&to_number,
'<=' => \&to_number,
;
sub new {
my $class = shift;
bless [], $class;
}
sub sort {
my $self = CORE::shift;
@$self = CORE::sort { $a->get_global_pos <=> $b->get_global_pos } @$self;
$self->remove_duplicates;
return $self;
}
sub remove_duplicates {
my $self = CORE::shift;
my @unique;
my $last_node=0;
foreach my $node (@$self) {
push @unique, $node unless( $node == $last_node);
$last_node= $node;
}
@$self= @unique;
return $self;
}
sub pop {
my $self = CORE::shift;
CORE::pop @$self;
}
sub push {
my $self = CORE::shift;
my (@nodes) = @_;
CORE::push @$self, @nodes;
}
sub append {
my $self = CORE::shift;
my ($nodeset) = @_;
CORE::push @$self, $nodeset->get_nodelist;
}
sub shift {
my $self = CORE::shift;
CORE::shift @$self;
}
sub unshift {
my $self = CORE::shift;
my (@nodes) = @_;
CORE::unshift @$self, @nodes;
}
sub prepend {
my $self = CORE::shift;
my ($nodeset) = @_;
CORE::unshift @$self, $nodeset->get_nodelist;
}
sub size {
my $self = CORE::shift;
scalar @$self;
}
sub get_node { # uses array index starting at 1, not 0
my $self = CORE::shift;
my ($pos) = @_;
$self->[$pos - 1];
}
sub getRootNode {
my $self = CORE::shift;
return $self->[0]->getRootNode;
}
sub get_nodelist {
my $self = CORE::shift;
@$self;
}
sub to_boolean {
my $self = CORE::shift;
return (@$self > 0) ? XML::XPath::Boolean->True : XML::XPath::Boolean->False;
}
sub string_value {
my $self = CORE::shift;
return '' unless @$self;
return $self->[0]->string_value;
}
sub to_literal {
my $self = CORE::shift;
return XML::XPath::Literal->new(
join('', map { $_->string_value } @$self)
);
}
sub to_number {
my $self = CORE::shift;
return XML::XPath::Number->new(
$self->to_literal
);
}
1;
__END__
=head1 NAME
XML::XPath::NodeSet - a list of XML document nodes
=head1 DESCRIPTION
An XML::XPath::NodeSet object contains an ordered list of nodes. The nodes
each take the same format as described in L<XML::XPath::XMLParser>.
=head1 SYNOPSIS
my $results = $xp->find('//someelement');
if (!$results->isa('XML::XPath::NodeSet')) {
print "Found $results\n";
exit;
}
foreach my $context ($results->get_nodelist) {
my $newresults = $xp->find('./other/element', $context);
...
}
=head1 API
=head2 new()
You will almost never have to create a new NodeSet object, as it is all
done for you by XPath.
=head2 get_nodelist()
Returns a list of nodes. See L<XML::XPath::XMLParser> for the format of
the nodes.
=head2 string_value()
Returns the string-value of the first node in the list.
See the XPath specification for what "string-value" means.
=head2 to_literal()
Returns the concatenation of all the string-values of all
the nodes in the list.
=head2 get_node($pos)
Returns the node at $pos. The node position in XPath is based at 1, not 0.
=head2 size()
Returns the number of nodes in the NodeSet.
=head2 pop()
Equivalent to perl's pop function.
=head2 push(@nodes)
Equivalent to perl's push function.
=head2 append($nodeset)
Given a nodeset, appends the list of nodes in $nodeset to the end of the
current list.
=head2 shift()
Equivalent to perl's shift function.
=head2 unshift(@nodes)
Equivalent to perl's unshift function.
=head2 prepend($nodeset)
Given a nodeset, prepends the list of nodes in $nodeset to the front of
the current list.
=cut