XML-LibXML-Iterator-1.04/0000755000175000017500000000000010677256021013770 5ustar phishphishXML-LibXML-Iterator-1.04/test.pl0000644000175000017500000000066307562770754015326 0ustar phishphish# Before `make install' is performed this script should be runnable with # `make test'. After `make install' it should work as `perl test.pl' ######################### # change 'tests => 1' to 'tests => last_test_to_print'; use XML::LibXML::Iterator; print "OK\n"; ######################### # Insert your test code below, the Test module is use()ed here so read # its man page ( perldoc Test ) for help writing this test script. XML-LibXML-Iterator-1.04/lib/0000755000175000017500000000000010677255747014554 5ustar phishphishXML-LibXML-Iterator-1.04/lib/XML/0000755000175000017500000000000010677255747015214 5ustar phishphishXML-LibXML-Iterator-1.04/lib/XML/LibXML/0000755000175000017500000000000010677255747016303 5ustar phishphishXML-LibXML-Iterator-1.04/lib/XML/LibXML/Iterator.pm0000644000175000017500000003107210677255653020431 0ustar phishphish# # package XML::LibXML::Iterator; use strict; use XML::NodeFilter qw(:results); use vars qw($VERSION); $VERSION = '1.04'; use overload '++' => sub { $_[0]->nextNode(); $_[0]; }, '--' => sub { $_[0]->previousNode(); $_[0]; }, '<>' => sub { return wantarray ? $_[0]->_get_all() : $_[0]->nextNode(); }, ; sub new { my $class = shift; my $node = shift; return undef unless defined $node; my $self = bless {}, $class; $self->{FIRST} = $node; # $self->first; $self->{CURRENT} = undef; $self->{INDEX} = -1; $self->{ITERATOR} = \&default_iterator; $self->{FILTERS} = []; return $self; } sub iterator_function { my $self = shift; my $func = shift; return if defined $func and ref( $func ) ne "CODE"; $self->first; if ( defined $func ) { $self->{ITERATOR} = $func; } else { $self->{ITERATOR} = \&default_iterator; } } sub set_filter { my $self = shift; $self->{FILTERS} = [ @_ ]; } sub add_filter { my $self = shift; push @{$self->{FILTERS}}, @_; } sub current { return $_[0]->{CURRENT}; } sub index { return $_[0]->{INDEX}; } sub next { return $_[0]->nextNode(); } sub previous { return $_[0]->previousNode(); } sub nextNode { my $self = shift; my @filters = @{$self->{FILTERS}}; my $node = undef; if ( $self->{INDEX} != -1 ) { my $fv = FILTER_SKIP; unless ( scalar @filters > 0 ) { $fv = FILTER_DECLINED; } while ( 1 ) { $node = $self->{ITERATOR}->( $self, 1 ); last unless defined $node; foreach my $f ( @filters ) { $fv = $f->accept_node( $node ); last if $fv; } last if $fv == FILTER_ACCEPT or $fv == FILTER_DECLINED; } } else { $node = $self->first(); } if ( defined $node ) { $self->{CURRENT} = $node; if ( $node->isSameNode( $self->{FIRST} ) ) { $self->{INDEX} = 0; } else { $self->{INDEX}++; } } return $node; } sub previousNode { my $self = shift; my @filters = @{$self->{FILTERS}}; my $node = undef; my $fv = FILTER_SKIP; unless ( scalar @filters > 0 ) { $fv = FILTER_DECLINED; } while ( 1 ) { $node = $self->{ITERATOR}->( $self, -1 ); last unless defined $node; foreach my $f ( @filters ) { $fv = $f->accept_node( $node ); last if $fv; } last if $fv == FILTER_ACCEPT or $fv == FILTER_DECLINED; } if ( defined $node ) { $self->{CURRENT} = $node; $self->{INDEX}--; } return $node; } sub first { my $self = shift; if ( scalar @_ ) { $self->{FIRST} = shift; } $self->{CURRENT} = $self->{FIRST}; # this logic is required if the node is not allowed to be shown my @filters = @{$self->{FILTERS}||[]}; my $fv = FILTER_DECLINED; foreach my $f ( @filters ) { $fv = $f->accept_node( $self->{CURRENT} ); last if $fv; } $fv ||= FILTER_ACCEPT; unless ( $fv == FILTER_ACCEPT ) { return undef; } $self->{INDEX} = 0; return $self->current; } sub last { my $self = shift; while ($self->next) {} return $self->current; } sub iterate { my $self = shift; my $function = shift; return unless defined $function and ref( $function ) eq 'CODE' ; my $rv; my $node = $self->first; while ( $node ) { $rv = $function->($self,$node); $node = $self->next; } return $rv; } sub default_iterator { my $self = shift; my $dir = shift; my $node = undef; if ( $dir < 0 ) { return undef if $self->{CURRENT}->isSameNode( $self->{FIRST} ) and $self->{INDEX} <= 0; $node = $self->{CURRENT}->previousSibling; return $self->{CURRENT}->parentNode unless defined $node; while ( $node->hasChildNodes ) { $node = $node->lastChild; } } else { if ( defined $self->{CURRENT} ) { return undef if $self->{CURRENT}->isSameNode( $self->{FIRST} ) and $self->{INDEX} > 0; if ( $self->{CURRENT}->hasChildNodes ) { $node = $self->{CURRENT}->firstChild; } else { $node = $self->{CURRENT}->nextSibling; my $pnode = $self->{CURRENT}->parentNode; while ( not defined $node ) { last unless defined $pnode; $node = $pnode->nextSibling; $pnode = $pnode->parentNode unless defined $node; } } } else { $self->{CURRENT} = $self->{FIRST}; $node = $self->{CURRENT}; } } return $node; } # helper function for the <> operator # returns all nodes that have not yet been accessed sub _get_all { my $self = shift; my @retval = (); my $node; while ( $node = $self->next() ) { push @retval, $node; } return @retval; } 1; __END__ =pod =head1 NAME XML::LibXML::Iterator - XML::LibXML's Tree Iteration Class =head1 SYNOPSIS use XML::LibXML; use XML::LibXML::Iterator; my $doc = XML::LibXML->new->parse_string( $somedata ); my $iter= XML::LibXML::Iterator->new( $doc ); $iter->iterator_function( \&iterator_function ); # more control on the flow while ( $iter->nextNode ) { # do something } # operate on the entire tree $iter->iterate( \&callback_function ); =head1 DESCRIPTION XML::LibXML::Iterator is an iterator class for XML::LibXML parsed documents. This class allows to iterate the document tree as it were a linear data structure. It is possible to step back and forth between the nodes of the tree and do certain operations on that nodes. Different to XPath the nodes are not prefetched but will be calculated for each step. Therefore an iterator is sensible towards the current state of a document tree on each step, while XPath is only per query executed. =head2 What is an iterator? XML::LibXML offers by default a W3C DOM interface on the parsed XML documents. This tree has per definition four directions to be traversed: Up, down, foreward and backward. Therefore a tree can be considered two dimensional. Although a tree is still one more simple datastructure it is way to complex for some operations. So the XML::LibXML::Iterator class breaks the for operations down to only two: backward and forward. For some people this easier to understand than DOM or SAX as this follows more the way one actually reads an XML document. Therefore an iterator has three basic functions: =over 4 =item * nextNode() =item * current() =item * previousNode() =back That's it. With an iterator one does not have to decide when to dive into a subtree or find a parent. It is not even required to care about the boundaries of a certain level. The iterator will get the next node for you until there is no node left to handle. In short: An iterator will answer the question about what to do next. =head2 How to use XML::LibXML::Iterator? XML::LibXML::Iterator requires a parsed document or at least a node to operate on. This node is passed to the iterator class and will be used as the B node of the iteration. One can allways reset the iterator to the first node by using the first()-function. Once XML::LibXML::Iterator is initialized the tree can be traversed by using either next() or previous(). Both function will return a XML::LibXML::Node object if there is such object available. Since the current object hold by the iterator class is always available via the current() function. The following example may clearify this: # get the document from wherever you like my $doc = XML::LibXML->new->parse_stream( *SOMEINPUT ); # get the iterator for the document root. my $iter = XML::LibXML::Iterator->new( $doc->documentElement ); # walk through the document while ( $iter->nextNode() ) { my $curnode = $iter->current(); print $curnode->nodeType(); } # now get back to the beginning $iter->first(); my $curnode = $iter->current(); print $curnode->nodeType(); Actually the functions nextNode(), previousNode(), first(), last() and current() do return the node which is current after the operation. E.g. nextNode() moves to the next node if possible and then returns the node. Thus the while-loop in the example can be written as while ( $iter->nextNode() ) { print $_->nodeType(); } Note, that just relieing on the return value of next() and previous() is somewhat dangerous, because both functions return B in case of reaching the iteration boundaries. That means it is not possible to iterate past the last element or before the first one. =head2 Node Filters XML::LibXML::Iterator accepts XML::NodeFilters to limit the nodes made available to the caller. Any nodefilter applied to XML::LibXML::Iterator will test if a node returned by the iteration function is visible to the caller. Different to the DOM Traversal Specification, XML::LibXML::Iterator allows filter stacks. This means it is possible to apply more than a single node filter to your node iterator. =head2 Complex Iterations By default XML::LibXML::Iterator will access all nodes of a given DOM tree. An interation based on the default iterator will access each single node in the given subtree once. The order how the nodes will be accessed is given by the following order: node -> node's childnodes -> node's next sibling In combination with XML::Nodefilter this is best for a wide range of scripts and applications. Nevertheless this is still to restrictive for some applications. XML::LibXML::Iterator allows to change that behaviour. This is done by resetting XML::LibXML::Iterator's iterator function. By using the method iterator_function() to override the default iterator function, it is possible to implement iterations based on any iteration rule imaginable. A valid iterator function has to take two parameters: As the first parameter it will recieve the iterator object itself, as second the direction of the iteration will be passed. The direction is either 1 (for next()) or -1 (for previous()). As the iterator-function is called by next() and previous() the interator-function has to be aware about the iteration boundaries. In case the iteration would pass the boundary for that operation, the function has to return undefined. Also the iterator function has to return the new current node, instead of setting it itself. *DEVELOPER NOTE* In order a single stepping is rather limited, the direction is given by the sign of the passed integer value. The value of the passed parameter will be used as an indication how many steps should be done. Therefor the interation direction should be tested relative to '0' and not as a equation. A basic template for a iterator function therefore will look like this: sub iterator_func_templ { my $iter = shift; my $step = shift; my $node = undef; my $current = $iter->current(); if ( $step > 0 ) { # move forward } else { # move backward $step *= -1; # remove the sign } return $node; } =head2 Repeated Operation Another feature of XML::LibXML::Iterator is the ability to repeat a single operation on all nodes in scope. Instead of writing a loop one can specify the opeation as a function, that it applied on each node found. The function that does the trick, is named iterate(). iterate() takes again two parameter: First the iterator object, second the node to operate on. iterate() will iterate through the entire document starting with the first node. If one has already started an iteration, the internal position will be reset to the first node. The following example will show how this works: $iter->iterate( sub {my ($iter,$node)=@_; map {$iter->setNodeName( lc $iter->nodeName ) if $iter->nodeType != NAMESPACE_DECLARATION } ($node, $node->attributes); } ); This extra long line lowercases all tagnames and the names of the attributes in a given subtree. =head2 Functions =over 4 =item new($first_node) =item first() =item nextNode() =item previousNode() =item last() =item current() =item index() =item iterator_function($funcion_ref) =item set_filter(@filter_list) =item add_filter(@filter_list) =item iterate($function_ref) =back =head1 SEE ALSO L, L =head1 AUTHOR Christian Glahn, Ephish@cpan.orgE =head1 COPYRIGHT (c) 2002-2007, Christian Glahn. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut XML-LibXML-Iterator-1.04/lib/XML/LibXML/NodeList/0000755000175000017500000000000010677255747020024 5ustar phishphishXML-LibXML-Iterator-1.04/lib/XML/LibXML/NodeList/Iterator.pm0000644000175000017500000001062510677255566022156 0ustar phishphish# $Id: Iterator.pm,v 1.1.1.1 2002/11/08 17:18:36 phish Exp $ # package XML::LibXML::NodeList::Iterator; use strict; use XML::NodeFilter qw(:results); use vars qw($VERSION); $VERSION = "1.03"; use overload '++' => sub { $_[0]->nextNode(); $_[0]; }, '--' => sub { $_[0]->previousNode(); $_[0] }, '<>' => sub {return wantarray ? $_[0]->_get_all : $_[0]->nextNode(); }, ; sub new { my $class = shift; my $list = shift; my $self = undef; if ( defined $list ) { $self = bless [ $list, -1, [], ], $class; } return $self; } sub set_filter { my $self = shift; $self->[2] = [ @_ ]; } sub add_filter { my $self = shift; push @{$self->[2]}, @_; } # helper function. sub accept_node { foreach ( @{$_[0][2]} ) { my $r = $_->accept_node($_[1]); return $r if $r; } # no filters or all decline ... return FILTER_ACCEPT; } sub first { $_[0][1]=0; my $s = scalar(@{$_[0][0]}); while ( $_[0][1] < $s ) { last if $_[0]->accept_node($_[0][0][$_[0][1]]) == FILTER_ACCEPT; $_[0][1]++; } return undef if $_[0][1] == $s; return $_[0][0][$_[0][1]]; } sub last { my $i = scalar(@{$_[0][0]})-1; while($i >= 0){ if ( $_[0]->accept_node($_[0][0][$i]) == FILTER_ACCEPT ) { $_[0][1] = $i; last; } $i--; } if ( $i < 0 ) { # this costs a lot, but is more safe return $_[0]->first; } return $_[0][0][$i]; } sub current { if ( $_[0][1] >= 0 || $_[0][1] < scalar @{$_[0][0]} ) { return $_[0][0][$_[0][1]]; } return undef; } sub index { if ( $_[0][1] >= 0 || $_[0][1] < scalar @{$_[0][0]} ) { return $_[0][1]; } return undef; } sub next { return $_[0]->nextNode(); } sub previous { return $_[0]->previousNode(); } sub nextNode { my $nlen = scalar @{$_[0][0]}; if ( $nlen <= ($_[0][1] + 1)) { return undef; } my $i = $_[0][1]; $i = -1 if $i < 0; # assure that we end up with the first # element in the first iteration while ( 1 ) { $i++; return undef if $i >= $nlen; if ( $_[0]->accept_node( $_[0][0]->[$i] ) == FILTER_ACCEPT ) { $_[0][1] = $i; last; } } return $_[0][0]->[$_[0][1]]; } sub previousNode { if ( $_[0][1] <= 0 ) { return undef; } my $i = $_[0][1]; while ( 1 ) { $i--; return undef if $i < 0; if ( $_[0]->accept_node( $_[0][0]->[$i] ) == FILTER_ACCEPT ) { $_[0][1] = $i; last; } } return $_[0][0][$_[0][1]]; } sub iterate { my $self = shift; my $funcref = shift; my $rv; return unless defined $funcref && ref( $funcref ) eq 'CODE'; $self->[1] = -1; # first element while ( my $node = $self->next ) { $rv = $funcref->( $self, $node ); } return $rv; } # helper function for the <> operator # returns all nodes that have not yet been accessed sub _get_all { my $self = shift; my @retval = (); my $node; while ( $node = $self->next() ) { push @retval, $node; } return @retval; } 1; =pod =head1 NAME XML::LibXML::NodeList::Iterator - Iteration Class for XML::LibXML XPath results =head1 SYNOPSIS use XML::LibXML; use XML::LibXML::NodeList::Iterator; my $doc = XML::LibXML->new->parse_string( $somedata ); my $nodelist = $doc->findnodes( $somexpathquery ); my $iter= XML::LibXML::NodeList::Iterator->new( $nodelist ); # more control on the flow while ( $iter->nextNode ) { # do something } # operate on the entire tree $iter->iterate( \&operate ); =head1 DESCRIPTION XML::LibXML::NodeList::Iterator is very similar to XML::LibXML::Iterator, but it does not iterate on the tree structure but on a XML::LibXML::NodeList object. Because XML::LibXML::NodeList is basicly an array the functionality of XML::LibXML::NodeList::Iterator is more restircted to stepwise foreward and backward than XML::LibXML::Iterator is. =head1 SEE ALSO L, L, L =head1 AUTHOR Christian Glahn, Ephish@cpan.orgE =head1 COPYRIGHT (c) 2002-2007, Christian Glahn. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut XML-LibXML-Iterator-1.04/Changes0000644000175000017500000000076510677255710015277 0ustar phishphishRevision history for Perl extension XML::LibXML::Iterator. 1.04 Fri Sep 28 2007 - fixed RT#29262 - minor documentation fixes 1.03 Mon Aug 06 2007 - fixed RT#28688 by using the provided patch 1.02 Sat Jun 23 2007 - fixed RT#6873 - cleaned up the tests - more compliance with the traversal specification 1.01 Sat Jun 23 2007 - fixed RT related bugs (though with a huge delay, sorry) 1.00 Fri Nov 8 2002 - extracted the modules from the main XML::LibXML bundle. XML-LibXML-Iterator-1.04/t/0000755000175000017500000000000010677255747014251 5ustar phishphishXML-LibXML-Iterator-1.04/t/03list.t0000644000175000017500000001733010677255624015552 0ustar phishphishuse Test; BEGIN { plan tests => 9; } use XML::LibXML; use XML::LibXML::NodeList::Iterator; my $xmlstr = "T"; sub t01_list_first_element { my $doc = XML::LibXML->new->parse_string( ''); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '/test/*' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); my $node = $iterator->next(); unless ( defined $node ) { print "# next did not return a node\n"; return 0; } unless ( $node->nodeName() eq 'n1' ) { print "# expected 'n1' received '" . $node->nodeName() . "'\n"; return 0; } return 1; } ok(t01_list_first_element()); sub t06_set_first { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//A | //B | //C' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); $iterator->first(); unless ( defined $iterator->current() ) { print "# there is no first node\n"; return 0; } unless ( $iterator->current()->nodeName() eq "A" ) { print "# expected nodeName 'A' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t06_set_first()); sub t07_set_last { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//A | //B | //C' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); $iterator->last(); unless ( defined $iterator->current() ) { print "# there is no last node\n"; return 0; } unless ( $iterator->current()->nodeName() eq "C" ) { print "# expected nodeName 'C' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t07_set_last()); sub t02_loop_forward { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//A|//B|//C' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); my $i = 0; while ( $iterator->nextNode() ) { $i++; } unless ( $i == 4 ) { print "# expected 4 iterations done " . $i . "\n"; return 0; } unless ( defined $iterator->current() ) { print "# wen out of scope\n"; return 0; } unless ( $iterator->current()->nodeName() eq "C" ) { print "# expected nodeName 'C' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } $iterator->first(); $i = 0; while ( $iterator->nextNode() ) { $i++; } unless ( $i == 3 ) { print "# expected 3 iterations done " . $i . "\n"; return 0; } unless ( defined $iterator->current() ) { print "# wen out of scope\n"; return 0; } unless ( $iterator->current()->nodeName() eq "C" ) { print "# expected nodeName 'C' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t02_loop_forward()); sub t03_loop_backward { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//A | //B | //C' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); my $i = 0; $iterator->last(); while ( $iterator->previousNode() ) { $i++; } unless ( $i == 3 ) { print "# expected 3 iterations done " . $i . "\n"; return 0; } unless ( defined $iterator->current() ) { print "# went out of scope!\n"; return 0; } unless ( $iterator->current()->nodeName() eq "A" ) { print "# expected nodeName 'A' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t03_loop_backward()); sub t04_loop_forward_backward { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//A | //B | //C' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); my $i = 0; while ( $iterator->nextNode() ) { $i++; } while ( $iterator->previousNode() ) { $i++; } unless ( $i == 7 ) { print "# expected 7 iterations done " . $i . "\n"; return 0; } unless ( defined $iterator->current() ) { print "# went out of scope!\n"; return 0; } unless ( $iterator->current()->nodeName() eq "A" ) { print "# expected nodeName 'A' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t04_loop_forward_backward()); sub t05_run_iterate { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//A | //B | //C' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); my $i = 0; $iterator->iterate( sub { $i++; } ); unless ( $i == 4 ) { print "# expected 4 iterations done " . $i . "\n"; return 0; } return 1; } ok(t05_run_iterate()); # RT#28688 package MyFilter; use base qw(XML::NodeFilter); use XML::NodeFilter qw(:results); use UNIVERSAL; sub accept_node { my $self = shift; my $node = shift; if (!UNIVERSAL::isa($node, 'XML::LibXML::Element')) { die "invalid node in MyFilter::accept_node()"; } return FILTER_DECLINED; } package main; sub t08_last_with_filter { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $nodelist = $doc->findnodes( '//*' ); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); $iterator->add_filter( MyFilter->new() ); $iterator->last(); unless ( defined $iterator->current() ) { print "# there is no last node\n"; return 0; } unless ( $iterator->current()->nodeName() eq "D" ) { print "# expected nodeName 'D' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t08_last_with_filter()); # END RT#28688 # RT#29262 sub t09_pass_nodes { my $doc = XML::LibXML->new->parse_string( '' ); my $nodelist = $doc->findnodes('/a/*'); my $iterator = XML::LibXML::NodeList::Iterator->new( $nodelist ); my $i = 0; my $cstr = ''; $iterator->iterate( sub { my($s, $n) = @_; if ( defined $n && $n->can('nodeName') ) { $i++; $cstr.=$n->nodeName(); } }); unless ( $i == 2 ) { print "# wrong number of nodes has been processed! $i\n"; return 0; } unless ( $cstr eq 'bc' ) { print "# wrong nodes have been processed! '$cstr'\n"; return 0; } return 1; } ok(t09_pass_nodes()); # END RT#29262 XML-LibXML-Iterator-1.04/t/01basic.t0000644000175000017500000000022610637220431015632 0ustar phishphishuse Test; BEGIN { plan tests => 1; } END { if ($loaded) { ok(1);} } use XML::LibXML::Iterator; use XML::LibXML::NodeList::Iterator; $loaded = 1; XML-LibXML-Iterator-1.04/t/02tree.t0000644000175000017500000001165310637220352015521 0ustar phishphishuse Test; BEGIN { plan tests => 7; } use XML::LibXML; use XML::LibXML::Iterator; my $xmlstr = "T"; my $libversion; eval { $libversion = XML::LibXML::LIBXML_VERSION(); }; sub t01_tree_first_element { my $doc = XML::LibXML->new->parse_string( ''); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); my $node = $iterator->nextNode(); unless ( defined $node ) { print "# next did not return a node\n"; return 0; } unless ( $node->nodeName() eq 'test' ) { print "# expected 'test' received '" . $node->nodeName() . "'\n"; return 0; } return 1; } ok(t01_tree_first_element()); sub t06_set_first { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); $iterator->first(); unless ( defined $iterator->current() ) { print "# there is no first node\n"; return 0; } unless ( $iterator->current()->nodeName() eq "A" ) { print "# expected nodeName 'A' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t06_set_first()); sub t07_set_last { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); $iterator->last(); unless ( defined $iterator->current() ) { print "# there is no last node\n"; return 0; } unless ( $iterator->current()->nodeName() eq "D" ) { print "# expected nodeName 'D' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t07_set_last()); sub t02_loop_forward { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); my $i = 0; while ( $iterator->nextNode() ) { $i++; } unless ( $i == 6 ) { print "# expected 6 iterations done " . $i . "\n"; return 0; } $iterator->first(); $i = 0; while ( $iterator->nextNode() ) { $i++; } unless ( $i == 5 ) { print "# expected 5 iterations done " . $i . "\n"; return 0; } unless ( defined $iterator->current() ) { print "# wen out of scope\n"; return 0; } unless ( $iterator->current()->nodeName() eq "D" ) { print "# expected nodeName 'D' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t02_loop_forward()); sub t03_loop_backward { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); my $i = 0; $iterator->last(); while ( $iterator->previousNode() ) { $i++; } unless ( $i == 5 ) { print "# expected 5 iterations done " . $i . "\n"; return 0; } return 1; } ok(t03_loop_backward()); sub t04_loop_forward_backward { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); my $i = 0; while ( $iterator->nextNode() ) { $i++; } while ( $iterator->previousNode() ) { $i++; } unless ( $i == 11 ) { print "# expected 11 iterations done " . $i . "\n"; return 0; } unless ( defined $iterator->current() ) { print "# went out of scope!\n"; return 0; } unless ( $iterator->current()->nodeName() eq "A" ) { print "# expected nodeName 'A' received '" . $iterator->current()->nodeName() . "'\n"; return 0; } return 1; } ok(t04_loop_forward_backward()); sub t05_run_iterate { my $doc = XML::LibXML->new->parse_string( $xmlstr ); unless ( defined $doc ) { print "# XML string was not parsed properly\n"; return 0; } my $iterator = XML::LibXML::Iterator->new( $doc->documentElement ); my $i = 0; $iterator->iterate( sub { $i++; } ); unless ( $i == 6 ) { print "# expected 6 iterations done " . $i . "\n"; return 0; } return 1; } ok(t05_run_iterate()); XML-LibXML-Iterator-1.04/MANIFEST0000644000175000017500000000034410677255750015132 0ustar phishphishChanges lib/XML/LibXML/Iterator.pm lib/XML/LibXML/NodeList/Iterator.pm Makefile.PL MANIFEST LICENSE README t/01basic.t t/02tree.t t/03list.t test.pl META.yml Module meta-data (added by MakeMaker) XML-LibXML-Iterator-1.04/Makefile.PL0000644000175000017500000000060507562770754015760 0ustar phishphishuse ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'XML::LibXML::Iterator', 'VERSION_FROM' => 'lib/XML/LibXML/Iterator.pm', 'PREREQ_PM' => { XML::LibXML => 1.52, XML::NodeFilter => 0 }, ); XML-LibXML-Iterator-1.04/LICENSE0000644000175000017500000000061010637221572014771 0ustar phishphishLICENSE ======= XML::LibXML::Iterator is free software, you may use it and distribute it under the same terms as Perl itself. Copyright 2002-2007, Christian Glahn, All rights reserved. DISCLAIMER ========== THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. XML-LibXML-Iterator-1.04/README0000644000175000017500000000126707562770754014673 0ustar phishphishXML::LibXML::Iterator version 1.00 ================================== XML::LibXML::Iterator implements the iterator part of the DOM Traversal and Range specification. This class allows to iterate through a DOM as it is done through an ordinary array. INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: XML::LibXML 1.52 or later. XML::NodeFilter 0.01 or later. COPYRIGHT AND LICENCE Copyright (C) 2002 Christian Glahn. All rights reserved. This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself. XML-LibXML-Iterator-1.04/META.yml0000644000175000017500000000062210677255747015257 0ustar phishphish# http://module-build.sourceforge.net/META-spec.html #XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# name: XML-LibXML-Iterator version: 1.04 version_from: lib/XML/LibXML/Iterator.pm installdirs: site requires: XML::LibXML: 1.52 XML::NodeFilter: 0 distribution_type: module generated_by: ExtUtils::MakeMaker version 6.30_01