home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Iterator.pm < prev    next >
Encoding:
Perl POD Document  |  2003-09-16  |  4.1 KB  |  184 lines

  1. # $Id: Iterator.pm,v 1.2 2003/09/16 18:18:18 joker Exp $
  2. #
  3. package XML::LibXML::NodeList::Iterator;
  4.  
  5. use strict;
  6. use XML::NodeFilter qw(:results);
  7.  
  8. use vars qw($VERSION);
  9. $VERSION = "1.00";
  10.  
  11. use overload
  12.   '++' => sub { $_[0]->next;     $_[0]; },
  13.   '--' => sub { $_[0]->previous; $_[0] },
  14.   '<>'  =>  sub {
  15.       if ( wantarray ) {
  16.           my @rv = ();
  17.           while ( $_[0]->next ){ push @rv,$_;}
  18.           return @rv;
  19.       } else {
  20.           return $_[0]->next
  21.       };
  22.   },
  23. ;
  24.  
  25. sub new {
  26.     my $class = shift;
  27.     my $list  = shift;
  28.     my $self  = undef;
  29.     if ( defined $list ) {
  30.         $self = bless [
  31.                        $list,
  32.                        0,
  33.                        [],
  34.                       ], $class;
  35.     }
  36.  
  37.     return $self;
  38. }
  39.  
  40. sub set_filter {
  41.     my $self = shift;
  42.     $self->[2] = [ @_ ];
  43. }
  44.  
  45. sub add_filter {
  46.     my $self = shift;
  47.     push @{$self->[2]}, @_;
  48. }
  49.  
  50. # helper function.
  51. sub accept_node {
  52.     foreach ( @{$_[0][2]} ) {
  53.         my $r = $_->accept_node($_[1]);
  54.         return $r if $r;
  55.     }
  56.     # no filters or all decline ...
  57.     return FILTER_ACCEPT;
  58. }
  59.  
  60. sub first    { $_[0][1]=0;
  61.                my $s = scalar(@{$_[0][0]});
  62.                while ( $_[0][1] < $s ) {
  63.                    last if $_[0]->accept_node($_[0][0][$_[0][1]]) == FILTER_ACCEPT;
  64.                    $_[0][1]++;
  65.                }
  66.                return undef if $_[0][1] == $s;
  67.                return $_[0][0][$_[0][1]]; }
  68.  
  69. sub last     {
  70.     my $i = scalar(@{$_[0][0]})-1;
  71.     while($i >= 0){
  72.         if ( $_[0]->accept_node($_[0][0][$i] == FILTER_ACCEPT) ) {
  73.             $_[0][1] = $i;
  74.             last;
  75.         }
  76.         $i--;
  77.     }
  78.  
  79.     if ( $i < 0 ) {
  80.         # this costs a lot, but is more safe
  81.         return $_[0]->first;
  82.     }
  83.     return $_[0][0][$i];
  84. }
  85.  
  86. sub current  { return $_[0][0][$_[0][1]]; }
  87. sub index    { return $_[0][1]; }
  88.  
  89. sub next     {
  90.     if ( (scalar @{$_[0][0]}) <= ($_[0][1] + 1)) {
  91.         return undef;
  92.     }
  93.     my $i = $_[0][1];
  94.     while ( 1 ) {
  95.         $i++;
  96.         return undef if $i >= scalar @{$_[0][0]};
  97.         if ( $_[0]->accept_node( $_[0][0]->[$i] ) == FILTER_ACCEPT ) {
  98.             $_[0][1] = $i;
  99.             last;
  100.         }
  101.     }
  102.     return $_[0][0]->[$_[0][1]];
  103. }
  104.  
  105. sub previous {
  106.     if ( $_[0][1] <= 0 ) {
  107.         return undef;
  108.     }
  109.     my $i = $_[0][1];
  110.     while ( 1 ) {
  111.         $i--;
  112.         return undef if $i < 0;
  113.         if ( $_[0]->accept_node( $_[0][0]->[$i] ) == FILTER_ACCEPT ) {
  114.             $_[0][1] = $i;
  115.             last;
  116.         }
  117.     }
  118.     return $_[0][0][$_[0][1]];
  119. }
  120.  
  121. sub iterate  {
  122.     my $self = shift;
  123.     my $funcref = shift;
  124.     return unless defined $funcref && ref( $funcref ) eq 'CODE';
  125.     $self->[1] = -1;
  126.     my $rv;
  127.     while ( $self->next ) {
  128.         $rv = $funcref->( $self, $_ );
  129.     }
  130.     return $rv;
  131. }
  132.  
  133. 1;
  134.  
  135. =pod
  136.  
  137. =head1 NAME
  138.  
  139. XML::LibXML::NodeList::Iterator - Iteration Class for XML::LibXML XPath results
  140.  
  141. =head1 SYNOPSIS
  142.  
  143.   use XML::LibXML;
  144.   use XML::LibXML::NodeList::Iterator;
  145.  
  146.   my $doc = XML::LibXML->new->parse_string( $somedata );
  147.   my $nodelist = $doc->findnodes( $somexpathquery );
  148.  
  149.   my $iter= XML::LibXML::NodeList::Iterator->new( $nodelist );
  150.  
  151.   # more control on the flow
  152.   while ( $iter->next ) {
  153.       # do something
  154.   }
  155.  
  156.   # operate on the entire tree
  157.   $iter->iterate( \&operate );
  158.  
  159. =head1 DESCRIPTION
  160.  
  161. XML::LibXML::NodeList::Iterator is very similar to
  162. XML::LibXML::Iterator, but it does not iterate on the tree structure
  163. but on a XML::LibXML::NodeList object. Because XML::LibXML::NodeList
  164. is basicly an array the functionality of
  165. XML::LibXML::NodeList::Iterator is more restircted to stepwise
  166. foreward and backward than XML::LibXML::Iterator is.
  167.  
  168. =head1 SEE ALSO
  169.  
  170. L<XML::LibXML::NodeList>, L<XML::NodeFilter>, L<XML::LibXML::Iterator>
  171.  
  172. =head1 AUTHOR
  173.  
  174. Christian Glahn, E<lt>christian.glahn@uibk.ac.atE<gt>
  175.  
  176. =head1 COPYRIGHT
  177.  
  178. (c) 2002, Christian Glahn. All rights reserved.
  179.  
  180. This package is free software; you can redistribute it and/or modify
  181. it under the same terms as Perl itself.
  182.  
  183. =cut
  184.