| 1 | #!/usr/bin/perl |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use warnings; |
|---|
| 5 | |
|---|
| 6 | use Test::More tests => 15; |
|---|
| 7 | use XML::XPathEngine; |
|---|
| 8 | |
|---|
| 9 | BEGIN { push @INC, './t'; } |
|---|
| 10 | |
|---|
| 11 | my $tree = init_tree(); |
|---|
| 12 | my $xp = XML::XPathEngine->new; |
|---|
| 13 | |
|---|
| 14 | #warn $tree->as_xml, "\n\n"; |
|---|
| 15 | { |
|---|
| 16 | my @root_nodes= $xp->findnodes( '/root', $tree); |
|---|
| 17 | is( join( ':', map { $_->value } @root_nodes), 'root_value', q{findnodes( '/root', $tree)}); |
|---|
| 18 | } |
|---|
| 19 | { |
|---|
| 20 | my @kid_nodes= $xp->findnodes( '/root/kid0', $tree); |
|---|
| 21 | is( scalar @kid_nodes, 2, q{findnodes( '/root/kid0', $tree)}); |
|---|
| 22 | } |
|---|
| 23 | { |
|---|
| 24 | my $kid_nodes= $xp->findvalue( '/root/kid0', $tree); |
|---|
| 25 | is( $kid_nodes, 'vkid2vkid4', q{findvalue( '/root/kid0', $tree)}); |
|---|
| 26 | } |
|---|
| 27 | { |
|---|
| 28 | is( $xp->findvalue( '//*[@att2="vv"]', $tree), 'gvkid1gvkid2gvkid3gvkid4gvkid5', |
|---|
| 29 | q{findvalue( '//*[@att2="vv"]', $tree)} |
|---|
| 30 | ); |
|---|
| 31 | is( $xp->findvalue( '//*[@att2]', $tree), 'gvkid1gkid2 1gvkid2gkid2 2gvkid3gkid2 3gvkid4gkid2 4gvkid5gkid2 5', |
|---|
| 32 | q{findvalue( '//*[@att2]', $tree)} |
|---|
| 33 | ); |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | is( $xp->findvalue( '//kid1[@att1=~/v[345]/]', $tree), 'vkid3vkid5', "match on attributes"); |
|---|
| 37 | |
|---|
| 38 | is( $xp->findvalue( '//@*', $tree), 'v1v1vvvxv2vvvxv3vvvxv4vvvxv5vvvx', 'match all attributes'); |
|---|
| 39 | is( $xp->findvalue( '//@*[parent::*/@att1=~/v[345]/]', $tree), 'v3v4v5', 'match all attributes with a test'); |
|---|
| 40 | |
|---|
| 41 | is( $xp->findvalue( '//kid1[@att1="v3"]/following::gkid2[1]', $tree), 'gkid2 4', "following axis[1]"); |
|---|
| 42 | is( $xp->findvalue( '//kid1[@att1="v3"]/following::gkid2[2]', $tree), 'gkid2 5', "following axis[2]"); |
|---|
| 43 | is( $xp->findvalue( '//kid1[@att1="v3"]/following::kid1/*', $tree), 'gvkid5gkid2 5', "following axis"); |
|---|
| 44 | is( $xp->findvalue( '//kid1[@att1="v3"]/preceding::gkid2[1]', $tree), 'gkid2 2', "preceding axis[1]"); |
|---|
| 45 | is( $xp->findvalue( '//kid1[@att1="v3"]/preceding::gkid2[2]', $tree), 'gkid2 1', "preceding axis[1]"); |
|---|
| 46 | is( $xp->findvalue( '//kid1[@att1="v3"]/preceding::gkid2', $tree), 'gkid2 1gkid2 2', "preceding axis"); |
|---|
| 47 | is( $xp->findvalue( 'count(//kid1)', $tree), '3', 'preceding count'); |
|---|
| 48 | |
|---|
| 49 | sub init_tree |
|---|
| 50 | { my $tree = tree->new( 'att', name => 'tree', value => 'tree'); |
|---|
| 51 | my $root = tree->new( 'att', name => 'root', value => 'root_value', att1 => 'v1'); |
|---|
| 52 | $root->add_as_last_child_of( $tree); |
|---|
| 53 | |
|---|
| 54 | foreach (1..5) |
|---|
| 55 | { my $kid= tree->new( 'att', name => 'kid' . $_ % 2, value => "vkid$_", att1 => "v$_"); |
|---|
| 56 | $kid->add_as_last_child_of( $root); |
|---|
| 57 | my $gkid1= tree->new( 'att', name => 'gkid' . $_ % 2, value => "gvkid$_", att2 => "vv"); |
|---|
| 58 | $gkid1->add_as_last_child_of( $kid); |
|---|
| 59 | my $gkid2= tree->new( 'att', name => 'gkid2', value => "gkid2 $_", att2 => "vx"); |
|---|
| 60 | $gkid2->add_as_last_child_of( $kid); |
|---|
| 61 | } |
|---|
| 62 | |
|---|
| 63 | $tree->set_pos; |
|---|
| 64 | |
|---|
| 65 | return $tree; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | package tree; |
|---|
| 70 | use base 'minitree'; |
|---|
| 71 | |
|---|
| 72 | sub getName { return shift->name; } |
|---|
| 73 | sub getValue { return shift->value; } |
|---|
| 74 | sub string_value { return shift->value; } |
|---|
| 75 | sub getRootNode { return shift->root; } |
|---|
| 76 | sub getParentNode { return shift->parent; } |
|---|
| 77 | sub getChildNodes { return wantarray ? shift->children : [shift->children]; } |
|---|
| 78 | sub getFirstChild { return shift->first_child; } |
|---|
| 79 | sub getLastChild { return shift->last_child; } |
|---|
| 80 | sub getNextSibling { return shift->next_sibling; } |
|---|
| 81 | sub getPreviousSibling { return shift->previous_sibling; } |
|---|
| 82 | sub isElementNode { return 1; } |
|---|
| 83 | sub get_pos { return shift->pos; } |
|---|
| 84 | sub getAttributes { return wantarray ? @{shift->attributes} : shift->attributes; } |
|---|
| 85 | sub as_xml |
|---|
| 86 | { my $elt= shift; |
|---|
| 87 | return "<" . $elt->getName . join( "", map { " " . $_->getName . '="' . $_->getValue . '"' } $elt->getAttributes) . '>' |
|---|
| 88 | . (join( "\n", map { $_->as_xml } $elt->getChildNodes) || $elt->getValue) |
|---|
| 89 | . "</" . $elt->getName . ">" |
|---|
| 90 | ; |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | sub cmp { my( $a, $b)= @_; return $a->pos <=> $b->pos; } |
|---|
| 94 | |
|---|
| 95 | 1; |
|---|
| 96 | |
|---|
| 97 | package att; |
|---|
| 98 | use base 'attribute'; |
|---|
| 99 | |
|---|
| 100 | sub getName { return shift->name; } |
|---|
| 101 | sub getValue { return shift->value; } |
|---|
| 102 | sub string_value { return shift->value; } |
|---|
| 103 | sub getRootNode { return shift->parent->root; } |
|---|
| 104 | sub getParentNode { return shift->parent; } |
|---|
| 105 | sub isAttributeNode { return 1; } |
|---|
| 106 | sub getChildNodes { return; } |
|---|
| 107 | |
|---|
| 108 | sub cmp { my( $a, $b)= @_; return $a->pos <=> $b->pos; } |
|---|
| 109 | |
|---|
| 110 | 1; |
|---|
| 111 | |
|---|