#!/bin/perl -w # $Id: /xmltwig/trunk/t/test_additional.t 25 2007-07-17T15:29:09.659907Z mrodrigu $ # test designed to improve coverage of the module use strict; use Carp; use File::Spec; use lib File::Spec->catdir(File::Spec->curdir,"t"); use tools; $|=1; my $DEBUG=0; use XML::Twig; my $perl= $]; my $open; BEGIN { if( $] < 5.008) { $open= sub { return }; } else { $open= eval( 'sub { open( $_[0], $_[1], $_[2]) }'); } } my $TMAX=663; print "1..$TMAX\n"; { my $t= XML::Twig->new->parse( q{ foo ]]> bar }); # use CDATA my $cdata= $t->first_elt( CDATA)->text; is( $cdata, 'cdata 01', 'first_elt( CDATA)');# test 1 is( $t->first_elt( CDATA)->cdata_string, '', 'cdata_string');# test 2 is( $t->root->cdata_string, '', 'cdata_string for non cdata element');# test 3 my $cdata2= $t->root->first_child( 'cdata[2]')->next_elt( CDATA)->text; is( $cdata2, 'cdata <02>', 'first_child( cdata[2])');# test 4 } # test warning for invalid options my $old_warning_handler= $SIG{__WARN__}; { my $warning=""; $SIG{__WARN__} = sub { $warning.= join '', @_ }; XML::Twig->new( dummy_opt => 1); $SIG{__WARN__}= $old_warning_handler; ok( $warning=~ m{^invalid option DummyOpt}, "expecting 'invalid option DummyOpt...', got '$warning'\n");# test 5 # test no warming if more_options is used $warning=""; $SIG{__WARN__} = sub { $warning.= join '', @_ }; XML::Twig->new( more_options => 1, dummy_opt => 1); $SIG{__WARN__}= $old_warning_handler; nok( $warning, "expecting no warning, got '$warning'\n");# test 6 $warning=""; $SIG{__WARN__} = sub { $warning.= join '', @_ }; XML::Twig::add_options( 'dummy_opt'); XML::Twig->new( dummy_opt => 1); $SIG{__WARN__}= $old_warning_handler; nok( $warning, "expecting no warning (2), got '$warning'\n");# test 7 } { # test do_not_chain_handlers my $nb_calls=0; my $t= XML::Twig->new( twig_handlers => { chain => sub { $nb_calls++; 1;}, 'doc/chain' => sub { $nb_calls++; 1;}, }, )->parse( 'chained'); is( $nb_calls, 2, "chained calls");# test 8 $nb_calls=0; $t= XML::Twig->new( twig_handlers => { chain => sub { $nb_calls++; 1 }, 'doc/chain' => sub { $nb_calls++; 1 }, }, do_not_chain_handlers => 1, )->parse( 'chained'); is( $nb_calls, 1, "not chained calls");# test 9 $nb_calls=0; $t= XML::Twig->new( twig_handlers => { chain => sub { $nb_calls++; 0; }, 'doc/chain' => sub { $nb_calls++; 0; }, }, )->parse( 'chained'); is( $nb_calls, 1, "chained handlers returning 0");# test 10 } # test ignore_elt { my $t= XML::Twig->new( ignore_elts => { i1 => 1, i2 => 2}) ->parse( ' '); my @t= $t->findnodes( '//t'); my $nb_t= scalar @t; is( $nb_t, 4, 'findnodes //t');# test 11 } # test elt_class { my $t= XML::Twig->new( elt_class => 'twig_test')->parse( ''); package twig_test; use base 'XML::Twig::Elt'; sub test { return 25 } package main; is( $t->root->test, 25, 'elt_class');# test 12 } # test char_handler { my $t= XML::Twig->new( char_handler => sub { my $s= shift; $s=~ s/\w/./g; return $s; }) ->parse( 'foobaz'); my $text= $t->root->text; is( $text, '......', 'silly char_handler');# test 13 my $att= $t->root->last_child( 'elt')->att( 'att'); is( $att, 'bar', 'last_child');# test 14 $att= $t->root->last_child( 'elt')->att( 'att'); # to use the cache is( $att, 'bar', 'last_child');# test 15 } # test various methods { my $t= XML::Twig->new->parse( ''); my @new_children= $t->root->children_copy; $t->set_id_seed( 'toto_'); $_->add_id foreach @new_children; my $id= $new_children[0]->att( 'id'); is( $id, 'toto_1', 'copy att');# test 16 $new_children[1]->change_att_name( id => 'foo'); my $foo= $new_children[1]->att( 'foo'); is( $foo, 'toto_2', 'change_att_name');# test 17 ok( $t->root->all_children_are( 'elt'), "all_children_are( 'elt')");# test 18 nok( $t->root->all_children_are( 'none'), "all_children_are( 'none')");# test 19 my $count= $t->root->children_count( 'elt'); is( $count, 2, "children_count( 'elt')");# test 20 $count= $t->root->children_count( 'none'); is( $count, 0, "children_count( 'none')");# test 21 $count= $t->root->children_count; is( $count, 2, "children_count");# test 22 ok( $t->root->first_child_matches( 'elt'), "first_child_matches");# test 23 $t->root->insert_new_elt( 'p'); nok( $t->root->all_children_are( 'elt'), "all_children_are( 'elt') (with p child)");# test 24 } # test cdata append_cdata, append_extra_data, append_pcdata { my $t=XML::Twig->new->parse( 'text more text'); my $cdata= $t->root->next_elt( CDATA)->cdata; is( $cdata, 'some cdata', 'created CDATA element');# test 25 $t->root->next_elt( CDATA)->append_cdata( ' appended<>'); $t->root->next_elt( PCDATA)->append_pcdata( 'more '); $t->root->first_child( 'elt')->append_extra_data( ''); is( $t->sprint, 'text more ]]> more text', "append_extra_data");# test 26 } # test att_names and att_to_field { my $t= XML::Twig->new->parse( ''); my $elt= $t->root->first_child_matches( 'elt'); ok( $elt, "first_child_matches");# test 27 my $att_names= join ':', sort $elt->att_names; is( $att_names, 'att1:att2', "att_names");# test 28 $elt->att_to_field( 'att1'); $elt->att_to_field( att2 => "new"); my $elt_string= $elt->sprint; is( $elt_string, 'barfoo', "att_to_field")# test 29 } # test child_matches child_text child_trimmed_text children_text { my $t= XML::Twig->new->parse( ' text text text'); my $root= $t->root; ok( $root->child_matches( 1, 'elt2'), "child_matches");# test 30 my $text= $root->child_text( 0); is( $text, ' text ', "child_text");# test 31 $text= $root->child_trimmed_text( -1, 'elt2'); is( $text, 'text text', "child_trimmed_text", 25 );# test 32 $text= join( '-', $root->children_text( qr/elt/)); is( $text, ' text - text text', "children_text");# test 33 } # test _ancestors _children _descendants { my $t= XML::Twig->new->parse( ''); is( tags( $t->root->_children), 'elt1:elt2', "_children");# test 34 is( tags( $t->root->_descendants), 'elt1:elt2:elt3', "_descendants");# test 35 is( $t->root->last_child_matches( 'elt3') ? "matches" : "no match",# test 36 "no match", "last_child_matches (no match)"); my $elt3= $t->root->last_child_matches( 'elt2')->first_child; is( $elt3->gi, 'elt3', "last_child_matches (match)");# test 37 is( tags( $elt3->_ancestors), 'elt2:doc', "_ancestors");# test 38 is( tags( $elt3->_ancestors(1)), 'elt3:elt2:doc', "_ancestors(1)");# test 39 is( tags( $t->root->descendants( 'elt1')), 'elt1', 'descendants with gi');# test 40 is( tags( $t->root->descendants()), 'elt1:elt2:elt3', 'descendants without gi');# test 41 is( tags( $t->root->descendants( qr/^elt/)), 'elt1:elt2:elt3', 'descendants with qr');# test 42 is( tags( $t->root->descendants( qr/^elt/)), 'elt1:elt2:elt3', 'descendants with qr (using cache)');# test 43 } # test comment methods { my $t= XML::Twig->new( comments => 'process') ->parse( 'text '); my $comment= $t->first_elt( '#COMMENT'); is( $comment->comment, ' foo ', "comment");# test 44 is( $comment->comment_string, '', "comment");# test 45 } # test element creation { my $t= XML::Twig->new->parse( ''); my $root= $t->root; my $elt= $root->insert_new_elt( first_child => 'elt'); my $elt3= $elt->insert_new_elt( after => elt3 => "elt3 text"); my $elt2= $elt3->insert_new_elt( before => elt2 => { att => "foo" }, "elt2 text"); is( $t->sprint, 'elt2 textelt3 text',# test 46 "insert_new_elt"); $root->cut_children; is( $t->sprint, '', "cut_children");# test 47 $elt= $root->insert_new_elt( last_child => 'elt' => { '#ASIS' => 1 }, "

bar

"); is( $elt->is_asis ? 'asis' : 'not asis', 'asis', "is_asis (initial, yes)");# test 48 is( $t->sprint, '

bar

', "insert_new_elt (ASIS)");# test 49 $elt->set_not_asis; is( $elt->is_asis ? 'asis' : 'not asis', 'not asis', "is_asis (unset, no)");# test 50 is( $t->sprint, '<p>bar</p>', "set_not_asis");# test 51 $elt->set_asis; is( $elt->is_asis ? 'asis' : 'not asis', 'asis', "is_asis (set, yes)");# test 52 is( $t->sprint, '

bar

', "set_asis");# test 53 $root->cut_children; $root->insert_new_elt( first_child => '#CDATA' => "toto"); is( $t->sprint, '', "create CDATA");# test 54 is($root->last_child_matches( '#CDATA') ? "match" : "no match", "match", "last_child_matches (yes)");# test 55 is($root->last_child_matches( "foo") ? "match" : "no match", "no match", "last_child_matches (no)");# test 56 my $cdata= $root->last_child_matches( '#CDATA'); ok( $cdata->is_cdata, "cdata is_cdata");# test 57 nok( $cdata->is_comment, "cdata is_comment");# test 58 nok( $cdata->is_pi, "cdata is_pi");# test 59 nok( $cdata->is_empty, "cdata is_empty");# test 60 nok( $cdata->is_ent, "cdata is_ent");# test 61 ok( $cdata->is_first_child, "cdata is_first_child");# test 62 ok( $cdata->is_last_child, "cdata is_last_child");# test 63 } # test field last_child_text last_child_trimmed_text { my $t= XML::Twig->new->parse( 'val1val2'); my $root= $t->root; $root->set_field( field2 => "new val2 "); is( $root->last_child_text( 'field2'), "new val2 ", "set_field");# test 64 is( $root->last_child_trimmed_text( 'field2'), "new val2", "set_field (trimmed text)");# test 65 is( $root->last_child_text( 'field1'), "val1", "last_child_text");# test 66 $root->set_field( field3 => "val3"); is( $t->sprint, 'val1new val2 val3',# test 67 "set_field (new field)"); } # test next/prev navigation functions { my $t= XML::Twig->new->parse( q{elt 1 elt 2 elt 3elt 4 elt 5 } ); my $root= $t->root; my $elt1= $t->getElementById( 'elt_1'); is( $elt1->sprint, 'elt 1', "getElementById");# test 68 my $sect= $elt1->getElementById( 'sect_1'); is( $sect->sprint, 'elt 3elt 4', "getElementById (sect)");# test 69 ok( $elt1->next_elt_matches( '#PCDATA[text()="elt 1"]'), "next_elt_matches (elt1 => elt)");# test 70 ok( $elt1->prev_elt_matches( 'doc'), "prev_elt_matches (elt1 => doc)");# test 71 ok( $sect->next_elt_matches( 'elt[@id="elt_3"]'), "next_elt_matches (sect => elt_3)");# test 72 ok( $sect->prev_elt_matches( '#PCDATA[text()="elt 2"]'), "prev_elt_matches (sect => elt_2)");# test 73 is( $sect->next_elt_text( 'elt[@id="elt_5"]'), 'elt 5 ', "next_elt_text");# test 74 is( $sect->next_elt_trimmed_text( 'elt[@id="elt_5"]'), 'elt 5', "next_elt_trimmed_text");# test 75 nok( $sect->next_elt( $sect, 'elt[@id="elt_5"]'), "next_elt (outside the subtree)");# test 76 nok( $sect->next_elt_text( $sect, 'elt[@id="elt_5"]'), "next_elt_text (outside the subtree)");# test 77 is( $sect->first_child_trimmed_text, "elt 3", "first_child_trimmed_text");# test 78 is( $sect->first_child_trimmed_text( 'goofy'), "", "first_child_trimmed_text (no child)");# test 79 # test comparisons $elt1 < $sect < $elt3 my $elt3= $t->elt_id( 'elt_3'); ok( $elt1->le( $sect), "\$elt1 le \$sect");# test 80 ok( $elt1->lt( $sect), "\$elt1 lt \$sect");# test 81 nok( $elt1->ge( $sect), "\$elt1 ge \$sect");# test 82 nok( $elt1->gt( $sect), "\$elt1 gt \$sect");# test 83 nok( $elt3->le( $sect), "\$elt3 le \$sect");# test 84 nok( $elt3->lt( $sect), "\$elt3 lt \$sect");# test 85 ok( $elt3->ge( $sect), "\$elt3 ge \$sect");# test 86 ok( $elt3->gt( $sect), "\$elt3 gt \$sect");# test 87 } # test keep_attribute_order { eval { require Tie::IxHash; }; if( $@) { skip( 7, "Tie::IxHash not available"); } else { import Tie::IxHash; my $t= XML::Twig->new( keep_atts_order => 1) ->parse( ''); is( $t->sprint, '', "keep_atts_order");# test 88 ok( $t->keep_atts_order, "keep_atts_order");# test 89 $t= XML::Twig->new->parse( ''); is( $t->sprint, '', "do not keep_atts_order");# test 90 nok( $t->keep_atts_order, "keep_atts_order not used");# test 91 $t->set_keep_atts_order(1); my $elt1= $t->root->new( 'elt'); $elt1->set_att( a1 => 'v1'); $elt1->set_att( a2 => 'v2'); is( $elt1->sprint, '', 'keep_atts_order with new elt');# test 92 my $elt2= $t->root->new( 'elt'); $elt2->set_att( a2 => 'v2'); $elt2->set_att( a1 => 'v1'); is( $elt2->sprint, '', 'keep_atts_order with new elt (reverse order)');# test 93 XML::Twig::Elt::set_keep_atts_order(0); my $elt3= $t->root->new( 'elt'); $elt3->set_att( a2 => 'v2'); $elt3->set_att( a1 => 'v1'); is( $elt3->sprint, '', 'no keep_atts_order with new elt (reverse order)');# test 94 } } # test wrap_children xml_string { my $t= XML::Twig->new->parse( ''); $t->set_id_seed( 'id_');; $t->root->wrap_children( '+', wrap => { foo => "bar"}); is( $t->sprint, '', "wrap_children");# test 95 $t->root->strip_att( 'id'); is( $t->sprint, '', "wrap_children");# test 96 is( $t->root->xml_string, '', "xml_string");# test 97 } # test set_output_encoding xml_text { my $t= XML::Twig->new->parse( 'elt 1 elt 2'); is( $t->root->xml_text, 'elt 1 elt 2', "xml_text");# test 98 is( $t->root->xml_string, 'elt 1 elt 2', "xml_text");# test 99 $t->set_output_filter( sub { return '.' x length $_[0] }); is( $t->root->xml_text, '...........', "xml_text (encoded)");# test 100 is( $t->root->xml_string, '.................................', "xml_text (encoded)");# test 101 } # is_first_child is_last_child test contains_a_single contains_only { my $t= XML::Twig->new->parse( q{ e2_1 e2_2e2_3 e2_4e2_5e3_1 }); my $elt1= $t->root->first_child('*'); my $elt2= $t->root->child( 1); my $elt3= $t->root->first_child( sub { $_[0]->children_count( 'elt3') == 1 }); my $elt4= $t->root->last_child; nok( $t->root->child( 6), 'child(6)');# test 102 nok( $t->root->child( -6), 'child(-6)');# test 103 nok( $t->root->child( 1, 'foo'), 'child(1, foo)');# test 104 nok( $t->root->child( -1, 'foo'), 'child(-1, foo)');# test 105 nok( $elt4->child( 1), 'child(1) on empty elt on empty elt');# test 106 nok( $elt4->child( 1, 'foo'), 'child(1, foo) on empty elt');# test 107 nok( $elt4->child( -1), 'child(-1) on empty elt');# test 108 nok( $elt4->child( -1, 'foo'), 'child(-1, foo) on empty elt');# test 109 ok( $elt1->is_first_child, "\$elt1->is_first_child");# test 110 nok( $elt2->is_first_child, "\$elt2->is_first_child is false");# test 111 nok( $elt3->is_first_child, "\$elt3->is_first_child is false");# test 112 nok( $elt1->is_last_child, "\$elt1->is_last_child");# test 113 nok( $elt2->is_last_child, "\$elt2->is_last_child");# test 114 ok( $elt4->is_last_child, "\$elt3->is_last_child is false");# test 115 ok( $elt1->contains_a_single( 'elt2'), "\$elt1->contains_a_single( 'elt2')");# test 116 nok( $elt1->contains_a_single( 'elt'), "\$elt1->contains_a_single( 'elt')");# test 117 nok( $elt2->contains_a_single( 'elt2'), "\$elt2->contains_a_single( 'elt2')");# test 118 nok( $elt3->contains_a_single( 'elt2'), "\$elt3->contains_a_single( 'elt2')");# test 119 nok( $elt4->contains_a_single( 'elt2'), "\$elt4->contains_a_single( 'elt2')");# test 120 ok( scalar $elt1->contains_only( 'elt2'), "\$elt1->contains_only( 'elt2')");# test 121 nok( $elt1->contains_only( 'elt'), "\$elt1->contains_only( 'elt') is false");# test 122 ok( scalar $elt2->contains_only( 'elt2'), "\$elt2->contains_only( 'elt2')");# test 123 nok( $elt3->contains_only( 'elt2'), "\$elt3->contains_only( 'elt2') is false");# test 124 ok( $elt4->contains_only( 'elt2'), "elt4->contains_only( 'elt2')");# test 125 is( $elt1->next_sibling_text, $elt2->text, "next_sibling_text");# test 126 is( $elt1->next_sibling_text, $elt2->text, "next_sibling_text using the cache");# test 127 is( $elt1->parent_text, $t->root->text, "parent_text");# test 128 is( $elt1->parent_text('doc'), $t->root->text, "parent_text");# test 129 is( $elt1->first_child->parent_text('doc'), $t->root->text, "parent_text");# test 130 ok( $elt2->parent_matches( 'doc'), "elt->parent_matches( 'doc')");# test 131 nok( $elt2->parent_matches( 'elt'), "elt->parent_matches( 'elt') is false");# test 132 nok( $t->root->parent, 'root parent');# test 133 nok( $t->root->parent_matches( 'doc'), 'root parent( doc)');# test 134 nok( $t->root->parent_matches( 'foo'), 'root parent( foo)');# test 135 is( $elt2->level, 1, "level");# test 136 is( $elt2->level( 'elt'), 0, "level( elt)");# test 137 is( $elt2->level( 'doc'), 1, "level( doc)");# test 138 is( $elt2->level( 'foo'), 0, "level( foo)");# test 139 nok( $elt2->first_child_text( 'foo'), "first_child_text on empty elt( 'foo')");# test 140 nok( $elt2->first_child_trimmed_text( 'foo'), "first_child_trimmed_text on empty elt( 'foo')");# test 141 nok( $elt4->next_sibling, 'next_sibling on last');# test 142 nok( $elt4->first_child, 'first_child on empty');# test 143 nok( $elt4->last_child, 'last_child on empty');# test 144 nok( $elt4->next_sibling_text, 'next_sibling_text on last');# test 145 nok( $elt4->first_child_text, 'first_child_text on empty');# test 146 nok( $elt4->last_child_text, 'last_child_text on empty');# test 147 nok( $elt4->next_sibling_trimmed_text, 'next_sibling_trimmed_text on last');# test 148 nok( $elt4->first_child_trimmed_text, 'first_child_trimmed_text on empty');# test 149 nok( $elt4->last_child_trimmed_text, 'last_child_trimmed_text on empty');# test 150 nok( $elt1->prev_sibling, 'prev_sibling on last');# test 151 nok( $elt1->prev_sibling_text, 'prev_sibling_text on last');# test 152 nok( $elt1->prev_sibling_trimmed_text, 'prev_sibling_trimmed_text on last');# test 153 } # test next_n_elt del_id delete empty_tag_style { my $t= XML::Twig->new->parse( ''); my $elt= $t->root->next_n_elt( 1); is( $elt->gi, 'elt', "next_n_elt");# test 154 is( $t->elt_id( 'id1')->gi, 'elt', "elt_id");# test 155 $elt->del_id; is( $t->sprint, '', "del_id");# test 156 nok( $t->elt_id( 'id1'), "no elt_id( 'id1')");# test 157 $elt->set_id( 'id2'); is( $t->sprint, '', "set_id");# test 158 is( $t->elt_id( 'id2')->gi, "elt", "elt_id after set_id");# test 159 $elt->delete; is( $t->sprint, '', "delete");# test 160 $t->root->insert_new_elt( first_child => '#COMMENT' => "a comment"); is( $t->sprint, '', "add comment");# test 161 $elt= $t->root->insert_new_elt( last_child => elt => { '#EMPTY' => 1 }); is( $t->sprint, '', "empty element");# test 162 ok( $elt->is_empty, "\$elt is empty");# test 163 $elt->set_not_empty; is( $t->sprint, '', "non empty element");# test 164 nok( $elt->is_empty, "\$elt is not empty");# test 165 $elt->set_empty; ok( $elt->is_empty, "\$elt is empty");# test 166 is( $t->sprint, '', "empty element again");# test 167 $t->set_empty_tag_style( 'html'); is( $t->sprint, '', "empty element (html style)");# test 168 XML::Twig::Elt::set_empty_tag_style( 'expand'); is( $t->sprint, '', "empty element (expand style)");# test 169 $t->set_empty_tag_style( 'normal'); is( $t->sprint, '', "empty element (normal style)");# test 170 $elt->set_content( "toto"); nok( $elt->is_empty, "\$elt is not empty");# test 171 is( $t->sprint, 'toto', "element with content");# test 172 nok( $elt->prev_sibling_matches( '#PI'), "prev_sibling_matches nok");# test 173 my $comment= $elt->prev_sibling_matches( '#COMMENT'); ok( $comment, "prev_sibling_matches ok");# test 174 $comment= $elt->prev_sibling; is( $comment->gi, '#COMMENT', 'prev_sibling');# test 175 $comment= $elt->prev_sibling; is( $comment->gi, '#COMMENT', 'prev_sibling using the cached cond');# test 176 $comment= $elt->prev_sibling( '#COMMENT'); is( $comment->gi, '#COMMENT', 'prev_sibling');# test 177 $comment= $elt->prev_sibling( '#COMMENT'); is( $comment->gi, '#COMMENT', 'prev_sibling using the cached cond');# test 178 $comment->set_comment( "another comment"); is( $t->sprint, 'toto', "element with content");# test 179 $t->root->field_to_att( 'elt'); is( $t->sprint, '', "field_to_att");# test 180 $t->root->del_att( 'elt'); $t->root->first_child( '#COMMENT')->delete; is( $t->sprint, '', "back to a very simple doc");# test 181 $t->root->insert( elt => { att => "v2" }); $t->root->first_child->set_content( "val 3"); $t->root->insert_new_elt( first_child => elt => { att => "v1" }, "val 2"); $t->root->insert_new_elt( last_child => elt => { att => "v3" }, "val 1"); is( $t->sprint, 'val 2val 3val 1',# test 182 "insert 3 elements"); $t->root->sort_children_on_value; is( $t->sprint, 'val 1val 2val 3',# test 183 "sort_children_on_value"); $t->root->sort_children_on_att( "att", order => "reverse" ); is( $t->sprint, 'val 1val 3val 2',# test 184 "sort_children_on_att (reverse)"); $t->root->set_text( "fini fini"); is( $t->sprint, 'fini fini', 'set_text on root');# test 185 my $p= $t->root->insert( 'p'); my $new_p= $p->split_at( 4); is( $t->sprint, '

fini

fini

', "split_at");# test 186 my $alt1_p= $p->copy; my $alt2_p= $p->copy; $p->split( qr/(i)/, 'b' ); is( $p->sprint, '

fini

', "split");# test 187 $alt1_p->first_child->split( qr/(i)/, 'b' ); is( $alt1_p->sprint, '

fini

', "split");# test 188 $new_p->split( qr/(i)/, b => { foo => "bar" } ); is( $new_p->sprint, '

fini

', "split (with att)");# test 189 } # test start_tag_handlers { my @results; my $handler; my $t=XML::Twig->new( start_tag_handlers =>{ elt => \&sth1}); sub sth1 { my( $t, $elt)= @_; push @results, "handler 1: ". $elt->id; $handler= $t->setStartTagHandler( elt => \&sth2); } sub sth2 { my( $t, $elt)= @_; push @results, "handler 2: ". $elt->id; $t->setStartTagHandler( elt => $handler); } $t->parse( ''); is( shift @results, "handler 1: id1", "handler 1");# test 190 is( shift @results, "handler 2: id2", "handler 2");# test 191 is( shift @results, "handler 1: id3", "handler 1 again");# test 192 } { my $t= XML::Twig->new( pi =>'process')->parse( ''); my $pi= $t->root->first_child( '#PI'); $pi->set_target( 't2'); $pi->set_data( 'data2'); is( $pi->sprint, '', "pi");# test 193 my $elt= $pi->next_sibling; $elt->set_extra_data( ''); is( $elt->sprint, "", "elt with comment");# test 194 } { my $t= XML::Twig->new->parse( " elt 1 \n elt 2 "); my $elt1= $t->root->first_child; my $elt2= $t->root->last_child; is( $elt2->prev_sibling_text, ' elt 1 ', "prev_sibling_text");# test 195 is( $elt2->prev_sibling_trimmed_text, 'elt 1', "prev_sibling_trimmed_text");# test 196 is( $elt1->next_sibling_trimmed_text, 'elt 2', "next_sibling_trimmed_text");# test 197 ok( $elt1->next_sibling_matches( 'elt'), "next_sibling_matches ok");# test 198 nok( $elt2->next_sibling_matches( 'elt'), "next_sibling_matches nok");# test 199 is( $elt2->prev_elt_text( 'elt'), " elt 1 ", "prev_elt_text");# test 200 is( $elt2->prev_elt_trimmed_text( 'elt'), "elt 1", "prev_elt_trimmed_text");# test 201 is( $elt2->parent_trimmed_text, "elt 1 elt 2", "parent_trimmed_text");# test 202 is( $elt1->sibling( 1)->trimmed_text, "elt 2", "sibling(1)");# test 203 is( $elt2->sibling( -1)->trimmed_text, "elt 1", "sibling(-1)");# test 204 is( $elt1->sibling_text( 1), " elt 2 ", "sibling(1)");# test 205 is( $elt2->sibling_text( -1), " elt 1 ", "sibling(-1)");# test 206 is( scalar $elt1->next_siblings, 1, "next_siblings");# test 207 is( scalar $elt1->next_siblings( 'elt2'), 0, "next_siblings (none)");# test 208 } { my $t= XML::Twig->new->parse( ''); my $elt1= $t->first_elt( 'elt1'); my $elt2= $t->first_elt( 'elt2'); $elt2->move( before => $elt1); is( $t->sprint, '', "cut");# test 209 $elt2->cut; is( $t->sprint, '', "cut");# test 210 $elt2->replace( $elt1); is( $t->sprint, '', "replace");# test 211 $elt2->set_content( "toto"); $elt2->suffix( ":foo"); is( $elt2->xml_string, "toto:foo", "suffix");# test 212 $elt2->first_child( '#TEXT')->suffix( 'bar'); is( $elt2->xml_string, "toto:foobar", "suffix on pcdata elt");# test 213 $elt2->replace_with( $elt1); is( $t->sprint, '', "replace_with");# test 214 $elt1->set_content( "tto"); my $o= XML::Twig::Elt->new( b => "oo"); $o->paste_within( $elt1, 1); is( $t->sprint, 'tooto', "replace_with");# test 215 $o->new( t => {a => 1 }, 'ta')->paste_within( $t->first_elt( 'b')->first_child, 1); is( $t->sprint, 'totaoto', "replace_with");# test 216 } # test methods inherited from XML::Parser::Expat { my $t= XML::Twig->new( twig_handlers => { elt => \&test_inherited }) ->parse( 'toto'); sub test_inherited { my( $t, $elt)= @_; is( $t->depth, 2, "depth");# test 217 ok( $t->in_element( 'sect'), "in_element");# test 218 nok( $t->in_element( 'elt'), "in_element (false)");# test 219 ok( $t->within_element( 'sect'), "within_element");# test 220 ok( $t->within_element( 'doc'), "within_element");# test 221 nok( $t->within_element( 'elt'), "within_element (false)");# test 222 is( join( '/', $t->context), "doc/sect", "context");# test 223 is( $t->current_line, 1, "current_line");# test 224 is( $t->current_byte, 20, "current_byte");# test 225 is( $t->original_string, "", "original_string");# test 226 is( $t->recognized_string, "
", "recognized_string");# test 227 is( $t->current_element, "sect", "current_element");# test 228 if( $XML::Parser::VERSION>2.27) { is( $t->element_index, 3, "element_index"); }# test 229 else { is( $t->element_index, 2, "element_index"); } # alt test 229 $t->base( "foo"); is( $t->base, "foo", "base");# test 230 ok( $t->position_in_context( 1), "position_in_context");# test 231 my $xml= 'toto'; my $expected= '<elt>toto</elt>'; my $broken= '<elt>toto
'; my $xml_escape= $t->xml_escape( $xml); if( $xml_escape eq $broken) { warn "your version of expat/XML::Parser has a broken xml_escape method\n"; ok( 1, "xml_escape"); # test# test 232 } else { is( $xml_escape, $expected, "xml_escape"); } # alt test 232 $xml= 'toto'; $expected= '<elt>toto</elt>'; $broken= '<elt>toto
'; $xml_escape= $t->xml_escape( $xml, 'o'); if( $xml_escape eq $expected) { ok( 1, "xml_escape"); }# test 233 elsif( $xml_escape eq $broken) { ok( 1, "xml_escape"); } # alt test 233 else { is( $xml_escape, $expected, "xml_escape"); } # alt test 233 } } { my $t= XML::Twig->new( start_tag_handlers => { i => sub { $_[0]->ignore }, }, twig_handlers => { s => sub { $_[0]->finish }, } ) ->parse( 'foototototobar'); is( $t->sprint, "foototo", "ignore + finish");# test 234 } # test xml declaration and entity related methods { my $t= XML::Twig->new->parse( ' tata

"> ]> &ent1;&ent2;'); is( $t->xml_version, "1.0", "xml_version");# test 235 is( $t->encoding, "ISO-8859-1", "encoding");# test 236 nok( $t->standalone, "standalone (no)");# test 237 is( $t->xmldecl, qq{\n}, "xmldecl");# test 238 $t->set_xml_version( "1.1"); is( $t->xml_version, "1.1", "set_xml_version");# test 239 $t->set_encoding( "UTF-8"); is( $t->encoding, "UTF-8", "set_encoding");# test 240 $t->set_standalone( 1); ok( $t->standalone||'', "set_standalone");# test 241 is( $t->xmldecl, qq{\n}, "xmldecl");# test 242 is( join( ':', sort $t->entity_names), "ent1:ent2:ent3", "entity_names");# test 243 my $ent1= $t->entity( 'ent1'); is( $ent1->name, "ent1", "entity name");# test 244 is( $ent1->val, "toto", "entity val");# test 245 nok( $ent1->sysid, "entity sysid (none)");# test 246 nok( $ent1->pubid, "entity pubid (none)");# test 247 nok( $ent1->ndata, "entity ndata (none)");# test 248 my $ent3= $t->entity( 'ent3'); is( $ent3->name, "ent3", "entity name");# test 249 nok( $ent3->val, "entity val (none)");# test 250 is( $ent3->sysid, "ent3.png", "entity sysid");# test 251 nok( $ent3->pubid, "entity pubid (none)");# test 252 is( $ent3->ndata, "PNG", "entity ndata");# test 253 my $doctype= qq{\ntata

">\n\n]>\n}; is( $t->doctype, $doctype, "doctype");# test 254 my $ent4= $t->entity_list->add_new_ent( ent4 => "ent 4")->ent( 'ent4'); is( $ent4->text, qq{}, "add_new_ent");# test 255 my $ent5= $t->entity_list->add_new_ent( ent5 => "", "ent5.png", "", "PNG" )->ent( 'ent5'); is( $ent5->text, qq{}, "add_new_ent (ndata)");# test 256 is( join( ':', sort $t->entity_names), "ent1:ent2:ent3:ent4:ent5", "entity_names");# test 257 is( $t->doctype, $doctype, "doctype");# test 258 my $prolog=qq{ tata

"> ]> }; is( $t->prolog( UpdateDTD => 1), $prolog, "prolog, updated DTD");# test 259 $t->entity_list->delete( 'ent3'); is( join( ':', sort $t->entity_names), "ent1:ent2:ent4:ent5", "entity_names");# test 260 $t->entity_list->delete( ($t->entity_list->list)[0]); is( join( ':', sort $t->entity_names), "ent2:ent4:ent5", "entity_names");# test 261 } { my $t= XML::Twig->new( comments => 'process', pi =>'process') ->parse( 'text'); is( $t->root->first_child( '#COMMENT')->get_type, "#COMMENT", "get_type #COMMENT");# test 262 is( $t->root->first_child( '#PI')->get_type, "#PI", "get_type #PI");# test 263 is( $t->root->first_child( '#CDATA')->get_type, "#CDATA", "get_type #CDATA");# test 264 is( $t->root->first_child( '#PCDATA')->get_type, "#PCDATA", "get_type #PCDATA");# test 265 is( $t->root->get_type, "#ELT", "get_type #ELT");# test 266 my $cdata= $t->root->first_child( '#CDATA'); $cdata->set_cdata( "new cdata"); is( $cdata->sprint, "", "set_cdata");# test 267 my $copy= $t->root->copy; is( $copy->sprint, $t->root->sprint, 'copy of an element with extra data');# test 268 is( $t->sprint( pretty_print => 'indented'),# test 269 qq{text\n}, 'indented elt'); } { my $t= XML::Twig->new->parse( ' text &ent; more'); my $ent= $t->first_elt( '#ENT'); is( $ent->get_type, "#ENT", "get_type");# test 270 is( $ent->ent, '&ent;', "ent");# test 271 is( $ent->ent_name, 'ent', "ent_name");# test 272 $ent->set_ent( '&new_ent;'); is( $ent->ent, '&new_ent;', "new_ent ent");# test 273 is( $ent->ent_name, 'new_ent', "new_ent ent_name");# test 274 } { my $t= XML::Twig->new->parse( 'text xx more text xx end'); my $alt_root= $t->root->copy; $t->root->mark( ' (xx) ', b => { att => "y" }); is( $t->sprint, 'textxxmore textxxend', 'mark');# test 275 $alt_root->first_child->mark( ' (xx) ', b => { att => "y" }); is( $alt_root->sprint, 'textxxmore textxxend', 'mark text');# test 276 } { my $t= XML::Twig->new->parse( ''); is( $t->sprint, '', "before save_global_state");# test 277 $t->save_global_state; $t->set_quote( 'single'); is( $t->sprint, "", "after set_global_state");# test 278 $t->restore_global_state; is( $t->sprint, '', "after restore_global_state");# test 279 } { my $t= XML::Twig->new->parse( 'text bold text more text and text even more text'); $t->subs_text( 'text', 'stuff'); is( $t->sprint, "stuff bold stuff more stuff and stuff even more stuff", "subs_text");# test 280 $t->subs_text( qr{stuf+}, 'text'); is( $t->sprint, "text bold text more text and text even more text", "subs_text");# test 281 my $elt= $t->root->first_child; my $bold= $elt->first_child( 'b'); $bold->erase; is( $t->sprint, "text bold text more text and text even more text", "erase");# test 282 $elt->merge( $elt->next_sibling); is( $elt->first_child_text, "text bold text more text and text even more text", "merge_text");# test 283 } # more tests on subs_text { my $doc='

link to http://www.xmltwig.com but do not link to http://bad.com, though link to toto and link to http://www.xml.com

now http://www.nolink.com and do not link to this and do not link to http://www.bad.com and do not link to http://www.bad2.com and link to http://link.com also

'; my $expected='

see www.xmltwig.com but do not link to http://bad.com, though link to toto and see www.xml.com

now http://www.nolink.com and do not link to this and do not link to http://www.bad.com and do not link to http://www.bad2.com and see link.com also

'; my $t= XML::Twig->new->parse( $doc); my $got= $t->subs_text( qr{(?{ href => $1 }, $2)'); is( $got->sprint, $expected, 'complex substitution with subs_text');# test 284 } { my $doc='text

and more text

'; (my $expected= $doc)=~ s{ }{ }g; my $t= XML::Twig->new->parse( $doc); my $got= $t->subs_text( qr{ }, '&ent( " ")'); is( $got->sprint, $expected, 'creating entities with subs_text');# test 285 $t= XML::Twig->new->parse( $doc); my $ent=" "; $got= $t->subs_text( qr{ }, "&ent( '$ent')"); is( $got->sprint, $expected, 'creating entities from a variable with subs_text');# test 286 } { my $t= XML::Twig->new->parse( ' 03val 1 2val 2 4val 3 01val 4 05 '); $t->root->sort_children_on_field( 'key', type =>'numeric' ); my $expected= ' 01val 4 2val 2 03val 1 4val 3 05 '; $t->set_pretty_print( 'record_c'); $t->set_indent( ' '); is( $t->sprint, $expected, "sort_children_on_field");# test 287 XML::Twig::Elt::set_indent( ' '); } { my $t= XML::Twig->new( empty_tags => 'expand', pretty_print => 'none')->parse( ''); is( $t->sprint, "", "empty_tags expand");# test 288 is( $t->sprint( empty_tags => 'normal'), "", "empty_tags normal");# test 289 is( $t->sprint( pretty_print => 'indented', empty_tags => 'normal'), "\n \n\n", "empty_tags expand");# test 290 $t->set_pretty_print( 'none'); $t->set_empty_tag_style( 'normal'); } { if( $perl < 5.008) { skip( 3, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $out=''; my $out2=''; $open->( my $fh, ">", \$out); $open->( my $fh2, ">", \$out2); my $t= XML::Twig->new( empty_tags => 'expand', pretty_print => 'none')->parse( ''); $t->print( $fh); is( $out, "", "empty_tags expand");# test 291 $t->print( $fh2); is( $t->sprint( empty_tags => 'normal'), "", "empty_tags normal");# test 292 $out=''; $t->print( $fh); is( $t->sprint( pretty_print => 'indented', empty_tags => 'normal'), "\n \n\n", "empty_tags expand");# test 293 $t->set_pretty_print( 'none'); $t->set_empty_tag_style( 'normal'); } } { if( $perl < 5.008) { skip( 3, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $out=''; my $out2=''; $open->( my $fh, ">", \$out); $open->( my $fh2, ">", \$out2); my $t= XML::Twig->new( empty_tags => 'expand', pretty_print => 'none'); $t->parse( '')->flush( $fh); is( $out, "", "empty_tags expand");# test 294 $t->parse( '')->flush( $fh2); is( $t->sprint( empty_tags => 'normal'), "", "empty_tags normal");# test 295 $out=''; $t->parse( '')->flush( $fh); is( $t->sprint( pretty_print => 'indented', empty_tags => 'normal'), "\n \n\n", "empty_tags expand");# test 296 $t->set_pretty_print( 'none'); $t->set_empty_tag_style( 'normal'); } } { my $t= XML::Twig->new->parse( ' 03val 1 2val 2 4val 3 01val 4 '); $t->root->sort_children_on_field( 'key', type =>'numeric' ); my $expected= ' 01val 4 2val 2 03val 1 4val 3 '; $t->set_pretty_print( 'record_c'); $t->set_indent( ' '); is( $t->sprint, $expected, "sort_children_on_field");# test 297 $t->set_indent( ' '); } { my $t= XML::Twig->new( empty_tags => 'expand', pretty_print => 'none')->parse( ''); is( $t->sprint, "", "empty_tags expand");# test 298 is( $t->sprint( empty_tags => 'normal'), "", "empty_tags normal");# test 299 is( $t->sprint( pretty_print => 'indented', empty_tags => 'normal'), "\n \n\n", "empty_tags expand");# test 300 $t->set_pretty_print( 'none'); $t->set_empty_tag_style( 'normal'); } { my $t= XML::Twig->new->parse( ''); my $elt1= $t->root->first_child( 'elt'); my $elt2= $t->root->first_child( 'ns1:elt'); is( $elt1->namespace, "uri_def", "default namespace");# test 301 is( $elt2->namespace, "uri1", "namespace");# test 302 is( $elt1->namespace, "uri_def", "namespace default");# test 303 is( $elt1->namespace( 'ns1'), "uri1", "namespace not default");# test 304 is( join( ' - ', $elt1->current_ns_prefixes), '', "current_ns_prefixes");# test 305 is( join( ' - ', $elt2->current_ns_prefixes), ' - ns1', "current_ns_prefixes");# test 306 } { my $t=XML::Twig->new( ignore_elts => { i => 1 }); $t->parse( ''); is( $t->sprint, '', "setIgnoreEltsHandler");# test 307 } { my $t=XML::Twig->new; $t->setIgnoreEltsHandler( i => 'discard'); $t->parse( ''); is( $t->sprint, '', "setIgnoreEltsHandler");# test 308 } # test setEndTagHandler { my $called=""; my $t= XML::Twig->new( twig_roots => { title => 1 }); my $doc=q{title 1

title 2

}; $t->parse( $doc); is( $called, "", "no end_tag_handler");# test 309 $called= ''; $t->setEndTagHandler( sect => sub { $called.= ":" if( $called); $called .= $_[1]}); $t->parse( $doc); is( $called, "sect:sect", "end_tag_handler");# test 310 $called= ''; $t->setEndTagHandler( sect => sub { return }); $t->parse( $doc); is( $called, "", "empty end_tag_handler");# test 311 } # test replace_prefix { my $called=''; my $not_called=''; my $t= XML::Twig->new( namespaces => 1, map_xmlns => { "uri1" => "foo", "uri2" => "whatever" }, twig_handlers => { "foo:bar" => sub { $called.= ":" if( $called); $called .= $_->id }, "toto:bar" => sub { $not_called.= ":" if( $not_called); $not_called .= $_->id }, }, ); $t->parse( q{ }); is( $called, "ok1:ok2", "map_xmlns");# test 312 is( $not_called, "", "map_xmlns (no hit)");# test 313 } # test parser { my $t= XML::Twig->new( twig_handlers => { doc => sub { is( ref( $_[0]->parser), 'XML::Parser::Expat', "parser"); } },# test 314 ) ->parse( ""); is( ref( $t->parser), '', "parser (empty, after the parse)");# test 315 $t->set_doctype( doc => "doc.dtd"); is( $t->sprint, qq{\n}, "set_doctype");# test 316 $t->set_doctype( doc => "doc.dtd", "-//public id/"); is( $t->sprint, qq{\n}, "set_doctype");# test 317 $t->set_doctype( doc => "doc.dtd", '', qq{[]}); is( $t->sprint, qq{\n]>\n}, "set_doctype");# test 318 #set_doctype ($name, $system, $public, $internal) } { if( $perl < 5.008) { skip( 3, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $out=''; $open->( my $fh, ">", \$out); my $doc= q{

p1

p2

}; my $t= XML::Twig->new( twig_handlers => { flush => sub { $_->flush( $fh) } } ); $t->{twig_autoflush}=0; $t->parse( $doc); is( $out, q{

p1

p2

}, "flush");# test 319 close $fh; $out=""; $open->( $fh, ">", \$out); $t= XML::Twig->new( twig_handlers => { flush => sub { $_[0]->flush_up_to( $_->prev_sibling, $fh) } } ); $t->{twig_autoflush}=0; $t->parse( $doc); is( $out, q{

p1

p2

}, "flush_up_to");# test 320 $t= XML::Twig->new( twig_handlers => { purge => sub { $_[0]->purge_up_to( $_->prev_sibling->prev_sibling, $fh) } } ) ->parse( q{

p1

sp 1

}); is( $t->sprint, q{

sp 1

}, "purge_up_to");# test 321 } } # test next_n_elt for a twig { my $t= XML::Twig->new->parse( q{e 2e 3}); is_undef( $t->next_n_elt( 1), "next_n_elt(1)");# test 322 is( $t->next_n_elt( 3)->gi, "e2", "next_n_elt(3)");# test 323 is( $t->next_n_elt( 1, "e3")->gi, "e3", "next_n_elt(1, e3)");# test 324 nok( $t->next_n_elt( 2, "e3"), "next_n_elt(2, e3)");# test 325 is( join(':', map { $_->gi } $t->_children), 'doc', "\$t->_children");# test 326 } # test dtd_print { if( $perl < 5.008) { skip( 2, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { { my $out=''; $open->( my $fh, ">", \$out); my $t= XML::Twig->new()->parse( q{]>toto}); $t->dtd_print( $fh); is( $out, "\n\n]>\n", "dtd_print");# test 327 close $fh; } { my $out=""; $open->( my $fh, ">", \$out); my $t= XML::Twig->new( twig_handlers => { stop => sub { print $fh "[X]"; $_->set_text( '[Y]'); $_[0]->flush( $fh); $_[0]->finish_print( $fh); } }); $t->{twig_autoflush}=0; $t->parse( q{beforefinish}); select STDOUT; is( $out, q{[X]before[Y]finish}, "finish_print");# test 328 } } } # test set_input_filter { my $t=XML::Twig->new( input_filter => \&rot13) ->parse( q{text}); is( $t->sprint, q{grkg}, "input filter");# test 329 $t=XML::Twig->new; $t->parse( q{text}); is( $t->sprint, q{text}, "input filter (none)");# test 330 $t->set_input_filter( \&rot13); $t->parse( q{grkg}); is( $t->sprint, q{text}, "set_input_filter");# test 331 $t->parse( ''); is( $t->sprint, '',# test 332 "set_input_filter on comments and cdata"); } sub rot13 { $_[0]=~ tr/a-z/n-za-m/; $_[0]; } # test global_state methods { my $doc= q{

p 1

p 2

}; my $t=XML::Twig->new->parse( $doc); is( $t->sprint, $doc, "initial state");# test 333 my $state= $t->global_state; $t->set_pretty_print( 'indented'); $t->set_indent( 8); nok( $t->sprint eq $doc, "changed state");# test 334 $t->set_global_state( $state); is( $t->sprint, $doc, "re-set initial state");# test 335 $t->save_global_state; $t->set_pretty_print( 'nice'); $t->set_quote( 'single'); nok( $t->sprint eq $doc, "changed state");# test 336 $t->restore_global_state( $state); is( $t->sprint, $doc, "restored initial state");# test 337 } # test encoding functions { if( $perl < 5.008) { skip( 21, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { require Encode; import Encode; my $text= "\x{E9}t\x{E9}"; my $text_latin1 = encode( latin1 => $text); my $text_utf8 = encode( utf8 => $text); my $text_html="été"; my $text_safe= "été"; my $text_safe_hex= "été"; my $doc_latin1=qq{\n$text_latin1}; my $doc_utf8=qq{\n$text_utf8}; my $doc_html=qq{\n$text_html}; my $doc_safe=qq{\n$text_safe}; my $doc_safe_hex=qq{\n$text_safe_hex}; my $doc_escaped= xml_escape( $doc_html); my $t= XML::Twig->new( output_encoding => "ISO-8859-1")->parse( $doc_utf8); $t->save_global_state; is( $t->output_encoding, 'ISO-8859-1', "output_encoding (ISO-8859-1)");# test 338 is( $t->sprint, $doc_latin1, "output_encoding ISO-8859-1");# test 339 $t->set_output_encoding( "UTF-8"); is( $t->output_encoding, 'UTF-8', "output_encoding (UTF-8)");# test 340 is( $t->sprint, $doc_utf8, "output_encoding UTF-8");# test 341 $t->set_output_text_filter( 'safe'); is( $t->sprint, $doc_safe, 'safe');# test 342 $t->set_output_text_filter( 'safe_hex'); is( $t->sprint, $doc_safe_hex, 'safe_hex');# test 343 if( $perl == 5.008) { skip( 2 => "cannot use latin1_output_text_filter with perl $perl"); } else { $t->set_output_text_filter( $t->latin1 ); $t->set_output_encoding( "ISO-8859-1"); is( normalize_xml( $t->sprint( pretty_print => 'indented')), normalize_xml( $doc_latin1), 'latin1');# test 344 $t->set_output_filter( 'latin1' ); $t->set_output_encoding( "ISO-8859-1"); is( $t->sprint, $doc_latin1, 'latin1 (just the string)');# test 345 } $t->set_output_text_filter( ); $t->set_output_encoding( "UTF-8"); $t->restore_global_state; eval "require HTML::Entities"; if( $@) { skip( 4, "need HTML::Entities for those tests"); } elsif( $perl == 5.008) { skip( 4, "HTML::Entities don't seem to work well with perl 5.8.0 (the e acute becomes é instead of é)"); } else { import HTML::Entities; $t->save_global_state; $t->set_output_encoding( "UTF-8"); my $original_output_text_filter= $t->output_text_filter; $t->set_output_text_filter( "html"); my $html_output_text_filter= $t->output_text_filter; is( $t->sprint, $doc_html, "output_text_filter html");# test 346 $t->set_output_text_filter( $original_output_text_filter); is( $t->sprint, $doc_utf8, "no output_text_filter ");# test 347 my $original_output_filter= $t->output_filter; $t->set_output_filter( "html"); is( $t->sprint, $doc_escaped, "output_filter html");# test 348 $t->restore_global_state; $t->set_output_encoding( "UTF-8"); is( $t->sprint, $doc_utf8, "no output_text_filter ");# test 349 } $t->restore_global_state; $t->set_output_encoding(); eval "require Text::Iconv"; if( $@) { skip( 3, "need Text::Iconv for those tests"); } else { my $encoding= 'ISO-8859-1'; if( eval( '$t->iconv_convert( "$encoding");')) { $t->set_output_filter( $t->iconv_convert( $encoding) ); $t->set_encoding( $encoding); is( $t->encoding, $encoding, "set_encoding");# test 350 is( $t->sprint, $doc_latin1, "output_filter ISO-8859-1 (using Text::Iconv)");# test 351 $t->restore_global_state; $t->set_output_encoding( "UTF-8"); is( $t->sprint, $doc_utf8, "no output_filter ");# test 352 } else { if( $@=~ m{^Unsupported encoding: $encoding}) { skip( 3, "your version of iconv does not support $encoding"); } else { skip( 3, "odd error creating filter with iconv: $@"); } } } $t->restore_global_state; $t->set_output_encoding(); eval( 'require Unicode::Map8 && require Unicode::String;'); if( $@) { skip( 3, "need Unicode::Map8 and Unicode::String for those tests" ); } else { $t->set_output_filter( $t->unicode_convert( 'latin1') ); $t->set_encoding( "ISO-8859-1"); is( $t->encoding, "ISO-8859-1", "set_encoding");# test 353 is( $t->sprint, $doc_latin1, "output_filter latin-1 (using Unicode::*)");# test 354 $t->restore_global_state; $t->set_output_encoding( "UTF-8"); is( $t->sprint, $doc_utf8, "no output_filter ");# test 355 $t->restore_global_state; $t->set_output_encoding(); } $t->set_output_filter( $t->regexp2latin1 ); $t->set_encoding( "ISO-8859-1"); is( $t->encoding, "ISO-8859-1", "set_encoding");# test 356 is( $t->sprint, $doc_latin1, "output_filter latin-1 (using regexp2latin1)");# test 357 $t->restore_global_state; $t->set_output_encoding( "UTF-8"); is( $t->sprint, $doc_utf8, "no output_filter ");# test 358 $t->restore_global_state; $t->set_output_encoding(); } } # test SAX1 export { eval "require XML::Handler::YAWriter"; if( $@) { skip(3, "require XML::Handler::YAWriter"); } else { import XML::Handler::YAWriter; my $xmldecl= qq{}; my $body= qq{

text

}; my $doc= $xmldecl.$body; my $t= XML::Twig->new->parse( $doc); $t->root->set_att( '#priv' => 'private'); $t->root->insert_new_elt( last_child => '#private'); my $writer = XML::Handler::YAWriter->new( AsString => 1); is( normalize_xml( $t->toSAX1( $writer)), $doc, 'toSAX1');# test 359 $writer->start_document; $t->root->toSAX1( $writer); is( normalize_xml( $writer->end_document), $doc, 'root toSAX1');# test 360 my $doc_flush="

p 1

text more text

"; my $doc_flushed=qq{

p 1

a

text more text

}; $writer = XML::Handler::YAWriter->new( AsString => 1, Pretty => { CatchEmptyElement => 1 }); $writer->start_document; $SIG{__WARN__} = sub { }; $t= XML::Twig->new( twig_handlers => { add => sub { $_[0]->flush_toSAX1( $writer); $_->new( g => "a")->toSAX1( $writer); }, flush => sub { $_[0]->flush_toSAX1( $writer); }, } ) ->parse( $doc_flush); my $output= $t->flush_toSAX1( $writer) || ''; $SIG{__WARN__}= $old_warning_handler; is( normalize_xml( $output), $doc_flushed, 'root toSAX1');# test 361 } } # test SAX2 export { eval "require XML::SAX::Writer;"; if( $@) { skip(5, "XML::SAX::Writer not available"); } elsif( $XML::SAX::Writer::VERSION < 0.39) { skip( 5, "XML::SAX::Writer version 0.39 and above required to use SAX2 export"); } else { eval "require XML::Filter::BufferText;"; if( $@) { skip(5, "XML::Filter::BufferText not available"); } else { import XML::SAX::Writer; import XML::Filter::BufferText; my $output=''; my $writer = XML::SAX::Writer->new( Output => \$output); my $xmldecl= qq{}; my $body= qq{

text

foo:e textt

[
}; my $doc= $xmldecl.$body; my $xfbtv= $XML::Filter::BufferText::VERSION; if( $xfbtv < 1.01) { skip( 2, "XML::Filter::BufferText version $xfbtv has a bug in CDATA processing"); } else { my $t= XML::Twig->new( comments =>'process', pi => 'process')->parse( $doc); # add private data $t->root->set_att( '#priv' => 'private'); $t->root->insert_new_elt( last_child => '#private'); $t->toSAX2( $writer); is( normalize_xml( $output), $doc, 'toSAX2');# test 362 $output=''; $t->root->toSAX2( $writer); is( normalize_xml( $output), $body, 'flush_toSAX2');# test 363 } my $doc_flush="

p 1

text more text

"; my $doc_flushed=qq{

p 1

a

text more text

}; $output=''; my $t= XML::Twig->new( twig_handlers => { add => sub { $_[0]->flush_toSAX2( $writer); $_->new( g => "a")->toSAX2( $writer); }, flush => sub { $_[0]->flush_toSAX2( $writer); }, } ) ->parse( $doc_flush); $t->flush_toSAX2( $writer); is( normalize_xml( $output), $doc_flushed, 'flush_toSAX2');# test 364 $doc= qq{]>toto = &toto;}; $t= XML::Twig->new()->parse( $doc); $output=''; $writer = XML::SAX::Writer->new( Output => \$output); $t->toSAX2( $writer); $output=~ s{}{}s; # shows that in fact we have a problem with outputing the DTD is( normalize_xml( $output), 'toto = foo', 'toSAX2 with an entity');# test 365 $doc= qq{toto = &toto;}; $t= XML::Twig->new()->parse( $doc); $output=''; $writer = XML::SAX::Writer->new( Output => \$output); $t->toSAX2( $writer); is( normalize_xml( $output), normalize_xml( $doc), 'toSAX2 with a non expanded entity');# test 366 } } } # test flushed an twig_current status (not a very good test, but the methods are not used in practice) { my $t= XML::Twig->new->parse( ''); nok( $t->root->_flushed, "root is not flushed");# test 367 $t->root->_set_flushed; ok( $t->root->_flushed, "root is flushed");# test 368 $t->root->_del_flushed; nok( $t->root->_flushed, "root is not flushed");# test 369 nok( $t->root->{twig_current}, "root is not twig current");# test 370 $t->root->set_twig_current; ok( $t->root->{twig_current}, "root is twig current");# test 371 $t->root->del_twig_current; nok( $t->root->{twig_current}, "root is not twig current");# test 372 ok( $t->root->closed, "root is closed");# test 373 } # test ignore { my $t= XML::Twig->new( start_tag_handlers => { ignore => sub { $_[0]->ignore }, ignore_parent => sub { $_->parent->ignore }, }, ) ->parse( '

yes 1

no 1

yes 2

no 2

'); is( $t->sprint, '

yes 1

yes 2

', "ignore");# test 374 } # test subs_text with replacement { my $doc= 'text rep

text rep

text rep
'; (my $rep1= $doc)=~ s/rep/newr/g; (my $rep2= $doc)=~ s{rep}{new}g; (my $rep3= $rep2)=~ s{ }{ }g; my $t= XML::Twig->new->parse( $doc); $t->root->subs_text( qr/(r)ep/, 'new$1'); is( $t->sprint, $rep1, "subs_text");# test 375 $t->root->subs_text( qr/(new)r/, '&elt( b => $1)'); is( $t->sprint, $rep2, "subs_text (with elt)");# test 376 $t->root->subs_text( qr/ /, '&ent( " ")'); is( $t->sprint, $rep3, "subs_text (with ent)");# test 377 } # test handlers that are not activated in 5.8 package test_handlers; sub new { bless { } } sub recognized_string { return 'recognized_string'; } sub original_string { return 'original_string'; } package main; { if( $perl < 5.008) { skip( 4, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $out=''; $open->( my $fh, ">", \$out); my $stdout= select $fh; XML::Twig::_twig_print_original_default( test_handlers->new); select $stdout; close $fh; is( $out, 'original_string', 'twig_print_original_default');# test 378 $out=''; $open->( $fh, ">", \$out); select $fh; XML::Twig::_twig_print( test_handlers->new); select $stdout; close $fh; is( $out, 'recognized_string', 'twig_print');# test 379 $out=''; $open->( $fh, ">", \$out); select $fh; XML::Twig::_twig_print_end_original( test_handlers->new); select $stdout; close $fh; is( $out, 'original_string', 'twig_print_end_original');# test 380 $out=''; $open->( $fh, ">", \$out); select $fh; XML::Twig::_twig_print( test_handlers->new); select $stdout; close $fh; is( $out, 'recognized_string', 'twig_print');# test 381 } XML::Twig::_twig_print_entity; # does nothing! } { my %ents= ( foo => '"toto"', pile => 'SYSTEM "file.bar" NDATA bar'); my %ent_text = hash_ent_text( %ents); my $ent_text = string_ent_text( %ents); my $doc= ""; my $t= XML::Twig->new->parse( $doc); is( normalize_xml( $t->entity_list->text), $ent_text, 'entity_list');# test 382 my @entities= $t->entity_list->list; is( scalar @entities, scalar keys %ents, 'entity_list');# test 383 if( $perl < 5.008) { skip( (scalar( keys %ents) + 1), "need perl 5.8 or above to perform these tests (you have $perl)"); } else { foreach my $ent (@entities) { my $out=''; $open->( my $fh, ">", \$out); my $stdout= select $fh; $ent->print; close $fh; select $stdout; is( normalize_xml( $out), $ent_text{$ent->name}, "print $ent->{name}"); # 2 tests 384 - 385 } my $out=''; $open->( my $fh, ">", \$out); my $stdout= select $fh; $t->entity_list->print; close $fh; select $stdout; is( normalize_xml( $out), $ent_text, 'print entity_list');# test 386 } delete $ents{pile}; %ent_text = hash_ent_text( %ents); $ent_text = string_ent_text( %ents); $t->entity_list->delete( 'pile'); @entities= $t->entity_list->list; is( scalar @entities, scalar keys %ents, '1 entity deleted');# test 387 is( $t->entity_list->text, $ent_text, 'entity_list (one entity deleted)');# test 388 } { if( $perl < 5.008) { skip( 3, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $out1=''; $open->( my $fh1, ">", \$out1); my $out2=''; $open->( my $fh2, ">", \$out2); my $out3=''; $open->( my $fh3, ">", \$out3); my $stdout= select $fh3; my $t= XML::Twig->new( twig_handlers => { e => sub { $_->print( $fh2); print $fh1 "X"; $_[0]->finish_print( $fh1); }, }, ) ->parse( 'texte

text

more text

foo

'); print 'should be in $out3'; select $stdout; is( $out1, 'Xmore text

foo

', 'finish_print');# test 389 is( $out2, 'e

text

', 'print to fh');# test 390 is( $out3, 'should be in $out3', 'restoring initial fh');# test 391 } } # test prefix mappings package test_sax_prefix_mapping; sub new { return bless { out => 'start ' }; } sub start_element { my( $h, $element)= @_; $h->{out}.= "- start $element->{Name} "; } sub end_element { my( $h, $element)= @_; $h->{out}.= "- end $element->{Name} "; } sub start_prefix_mapping { my( $h, $map)= @_; $h->{out}.= "- map $map->{Prefix} to $map->{NamespaceURI} "; } sub end_prefix_mapping { my( $h, $map)= @_; $h->{out}.= "- end map $map->{Prefix} "; } sub end_document { my( $h, $document)= @_; return $h->{out}; } package main; { my $h= test_sax_prefix_mapping->new; my $t= XML::Twig->new->parse( q{

text

text

}); my $out= $t->toSAX2( $h); is( $out, 'start - map to uri1 - start doc - map p1 to uri2 - start p - start p1:e - end p1:e - end p - end map p1 - map p1 to uri3 - start p - start p1:e - end p1:e - end p - end map p1 - end doc - end map ', 'prefix mapping');# test 392 } # test parsing with keep_encoding (to check no spurious warnings are produced) { my $warnings=''; $SIG{__WARN__}= sub { $warnings .= shift; }; my $doc= '

text

more text > é

'; my $t= XML::Twig->new( keep_encoding => 1)->parse( $doc); $SIG{__WARN__}= $old_warning_handler; is( $warnings, '', 'keep_encoding with elements with no attributes');# test 393 is( $t->sprint, $doc, 'twig output');# test 394 } # test end_tag_handlers with ignore { my $out=''; my $t= XML::Twig->new( twig_roots => { p => 1 }, start_tag_handlers => { x => sub { $out .= "s" } }, twig_handlers => { n => sub { $out .="n";}, x => sub { $out .="e"; } }, ) ->parse( '

text text more text

'); is( $out, 'snese', 'end_tag_handlers without ignore');# test 395 $out=''; $t= XML::Twig->new( twig_roots => { p => 1 }, start_tag_handlers => { x => sub { $out .= "s"; $_->ignore } }, end_tag_handlers => { x => sub { $out .="e"; }, }, twig_handlers => { n => sub { $out .="n"; }, }, ) ->parse( '

text text more text

'); is( $out, 'sese', 'end_tag_handlers with ignore');# test 396 eval ' XML::Twig->new( start_tag_handlers => { x => sub { $out .= "s"; $_->ignore } }, end_tag_handlers => { x => sub { $out .="e"; }, }, twig_handlers => { n => sub { $out .="n"; }, }, ); '; matches( $@, '^you should not use EndTagHandlers without', "error using end_tag_handlers");# test 397 $out=''; $t= XML::Twig->new( force_end_tag_handlers_usage => 1, start_tag_handlers => { x => sub { $out .= "s"; $_->ignore } }, end_tag_handlers => { x => sub { $out .="e"; }, }, twig_handlers => { n => sub { $out .="n"; }, }, ) ->parse( '

text text more text

'); is( $out, 'sesen', 'end_tag_handlers with ignore and force_end_tag_handlers_usage');# test 398 } { my @doc=( "", "", "", "", ); my( @r1, @r2, @r3, @r4); my $t1= XML::Twig->new( ignore_elts => { lignore => 1 }, twig_handlers => { root => sub { push @r1, $_->tag; }, l1 => sub { push @r1, $_->tag; }, } ); my $t2= XML::Twig->new( twig_handlers => { root => sub { push @r2, $_->tag; }, lignore => sub { $_->parent( 'l1')->ignore; }, }, ); my $t3= XML::Twig->new( twig_handlers => { root => sub { push @r3, $_->tag; }, lignore => sub { $_->parent( 'l1')->ignore; }, }, end_tag_handlers => { l1 => sub { push @r3, $_[1]; }, }, force_end_tag_handlers_usage => 1 ); my $t4= XML::Twig->new( twig_roots => { l1 => sub { push @r4, 'l1 from roots handler'; }, lignore => sub { $_->parent( 'l1')->ignore; }, }, end_tag_handlers => { 'root/l1' => sub { push @r4, 'l1 from end_tag_handler'; }, }, ); my $i=0; foreach my $doc (@doc) { @r1=(); @r2=(); @r3=(); @r4=(); $i++; $t1->parse( $doc); is( join( ':', @r1), "l1:root", "ignore_elt with twig_handlers $i (checking that stack is properly resized)"); $t2->parse( $doc); is( join( ':', @r2), "root", "ignore_elt on ancestor with twig_handlers $i (checking that stack is properly resized)"); $t3->parse( $doc); is( join( ':', @r3), "l1:root", "ignore_elt on ancestor with twig_handlers and end_tag_handlers $i (checking that stack is properly resized)"); $t4->parse( $doc); is( join( ':', @r4), "l1 from end_tag_handler", "ignore_elt on ancestor with twig_roots and end_tag_handlers $i (checking that stack is properly resized)"); } } { my $warning=""; $SIG{__WARN__} = sub { $warning .= join '', @_ }; my $t= XML::Twig->new( dummy_opt2 => 1); $SIG{__WARN__}= $old_warning_handler; matches( $warning, '^invalid option', "warning for extra option");# test 399 } # test various handlers { my %got; my $doc= ' foobarfoono '; my @handler_exp= ( 'e', 'doc/e', '/doc/e', 'a[@a1]', 'a[@a2]', 'a[@a1="v11"]', 'a[@a1="v21"]', '*[@a1]', '*[@a1="v11"]', '*[@a1="v21"]', '*[@a1=~/^v21$/]', 't[string()="foobar"]', 't[string()=~ /^foo/]', 't[string()=~ /bar$/]', '_default_', ); my %handlers; foreach my $exp (@handler_exp) { my $code= "\$got{\$_->id}||=[]; push \@{\$got{\$_->id}}, '$exp'; 1"; my $sub= eval "sub { $code }"; die "oops, error in test, code is '$code'" if( $@); $handlers{$exp}= $sub; } my $t= XML::Twig->new( twig_handlers => \%handlers)->parse( $doc); my %expected= ( e1 => [ '/doc/e', 'doc/e', 'e' ], no1 => [ '_default_'], a1 => [ '*[@a1]', '*[@a1="v11"]', 'a[@a1]', 'a[@a2]', 'a[@a1="v11"]' ], a2 => [ '*[@a1]', '*[@a1="v21"]', 'a[@a1]', 'a[@a2]', 'a[@a1="v21"]', '*[@a1=~/^v21$/]' ], b1 => [ '*[@a1]', '*[@a1="v11"]' ], b2 => [ '*[@a1="v21"]', '*[@a1]', '*[@a1=~/^v21$/]'], t1 => [ 't[string()="foobar"]', 't[string()=~ /^foo/]', 't[string()=~ /bar$/]' ], t2 => [ 't[string()=~ /^foo/]' ], t3 => [ '_default_'], doc1 => [ '_default_'], ); foreach my $elt (sort keys %expected) { my $expected= join( ' - ', sort @{$expected{$elt}}); my $got= $got{$elt} ? join( ' - ', sort @{$got{$elt}}) : ''; is( $got, $expected, "handlers on $elt"); # 10 tests 400 - 409 } my %handlers2; my %got2; foreach my $exp (@handler_exp) { my $code= "\$got2{\$_->id}||=[]; push \@{\$got2{\$_->id}}, '$exp:2'; 1"; my $sub= eval "sub { $code }"; die "oops, error in test, code is '$code'" if( $@); $t->setTwigHandler( $exp, $sub); } $t->parse( $doc); foreach my $elt (sort keys %expected) { my $expected= join( ' - ', map { "$_:2" } sort @{$expected{$elt}}); my $got= $got2{$elt} ? join( ' - ', sort @{$got2{$elt}}) : ''; is( $got, $expected, "handlers on $elt (2)"); # 10 tests 410 - 419 } } { my $t= XML::Twig->new->parse( ''); $t->change_gi( elt1 => 'elt2'); $t->change_gi( elt3 => 'elt4'); is( $t->sprint, '', 'change_gi');# test 420 } # these do not pass (yet?) { my $doc= '

text

<ignored>

more text

'; my $t= XML::Twig->new( start_tag_handlers => { i => sub { $_->ignore( 'string') }}) ->parse( $doc); is( $t->sprint, '

text

more text

', 'ignore');# test 421 $t->set_keep_encoding( 1); $t->parse( $doc); is( $t->sprint, '

text

more text

', 'ignore');# test 422 XML::Twig::Elt::set_keep_encoding( 0); } { my $t= XML::Twig->new->parse( '

'); my $p= $t->first_elt( '*[@ns1:att=~/^f/]'); is( $p->namespace, 'uri', 'namespace on elt');# test 423 is( $p->namespace( 'ns1'), 'uri2', 'namespace with arg');# test 424 is( $p->namespace( 'xmlns'), 'http://www.w3.org/2000/xmlns/', 'namespace for xmlns');# test 425 is( $t->root->namespace(), '', 'default namespace');# test 426 is( $t->root->namespace( ''), '', 'namespace with arg default');# test 427 is( $t->root->namespace( 'xml'), 'http://www.w3.org/XML/1998/namespace', 'namespace for xml');# test 428 } { my $t= XML::Twig->new->parse( 'text'); is( $t->root->first_child( 'e[@att="foo"]')->id, 'e2', 'cond on att value');# test 429 is( $t->root->first_child( '*[@att="foo"]')->id, 'f1', 'cond on att value (with wc)');# test 430 is( $t->root->first_child( '*[@att="foo" and @id="e2"]')->id, 'e2', 'and cond on att value');# test 431 is( $t->root->first_child( '*[@att="foo" or @id="e2"]')->id, 'f1', 'and cond on att value');# test 432 is( $t->root->first_child( 't[string()="text"]')->id, 't1', 'string cond');# test 433 is( $t->root->first_child( '*[string()="text"]')->id, 't1', 'string cond wc');# test 434 is( $t->root->first_child( 't[string()=~/^t/]')->id, 't1', 'regexp cond');# test 435 is( $t->root->first_child( '*[string()=~/^t/]')->id, 't1', 'regexp cond wc');# test 436 is( $t->root->first_child( qr/^t/)->id, 't1', 'regexp cond wc');# test 437 my $sprint= $t->root->first_child( 't')->sprint; $t->root->first_child( 't')->change_att_name( 'foo'); is( $t->root->first_child( 't')->sprint, $sprint, 'change_att_name on non existent att');# test 438 my $ids= join ':', sort keys %{$t->{twig_id_list}}; my $elt= XML::Twig::Elt->new( 'e'); is( $elt->sprint, '', 'new elt');# test 439 $elt->del_id; is( $elt->sprint, '', 'del_id, no id');# test 440 $elt->set_id( 'new_e'); is( $elt->sprint, '', 'set_id');# test 441 my( $new_ids)= join ':', sort keys %{$t->{twig_id_list}}; is( $new_ids, $ids, 'set_id on elt not in the tree');# test 442 $elt->del_id; is( $elt->sprint, '', 'del_id, id removed');# test 443 nok( $t->first_elt( 'e')->next_elt( $t->first_elt( 'e')), 'next_elt on empty subtree');# test 444 nok( $t->first_elt( 'e')->next_elt($t->first_elt( 'e'), 'e'), 'next_elt on empty subtree');# test 445 is( $t->root->get_xpath( './e[1]', 0)->id, 'e1', 'get_xpath with ./');# test 446 is( $t->root->first_child->get_xpath( '/doc/e[1]', 0)->id, 'e1', 'get_xpath with /');# test 447 is( $t->root->first_child->get_xpath( '/doc/e[-1]', 0)->id, 'e3', 'get_xpath with /');# test 448 is( $t->root->first_child->get_xpath( './../e[2]', 0)->id, 'e2', 'get_xpath with ..');# test 449 is( $t->root->first_child->get_xpath( './../*[2]', 0)->id, 'f1', 'get_xpath with ../*[2]');# test 450 is( $t->root->first_child->get_xpath( './../*', 0)->id, 'e1', 'get_xpath with ../*');# test 451 } { my $t= XML::Twig->new->parse( ''); is( $t->root->cmp( $t->root), 0, 'cmp root with itself');# test 452 my $ne= $t->root->new( 'ne'); is( $ne->cmp( $ne), 0, 'cmp with itself');# test 453 is_undef( $t->root->cmp( $ne), 'cmp elt in different trees');# test 454 my $t_sprint= $t->sprint; $t->root->field_to_att( 'foo'); is( $t->sprint, $t_sprint, 'field_to_att on wrong field');# test 455 my $ne_sprint= $ne->sprint; $ne->field_to_att( 'foo'); is( $ne->sprint, $ne->sprint, 'field_to_att on wrong field (no child)');# test 456 $ne->prefix( 'p 1pr', 'asis'); is( $ne->sprint, 'p 1pr', 'prefix asis');# test 457 $ne->prefix( 'p 2', 'asis'); is( $ne->sprint, 'p 2p 1pr', 'prefix asis');# test 458 $ne->suffix( 's 1su', 'asis'); is( $ne->sprint, 'p 2p 1prs 1su', 'prefix asis');# test 459 $ne->suffix( 's 2', 'asis'); is( $ne->sprint, 'p 2p 1prs 1sus 2', 'prefix asis');# test 460 } { my $t= XML::Twig->new( twig_handlers => { w => sub { $_->wrap_in( 'ww'); } }) ->parse( '

text

'); is( $t->sprint, '

text

', 'wrap current elt');# test 461 $t->root->wrap_in( 'd'); is( $t->sprint, '

text

', 'wrap root');# test 462 } { my $t= XML::Twig->new( twig_handlers => { w => sub { $_->parent->wrap_in( 'ww'); } }) ->parse( '

text

'); is( $t->sprint, '

text

', 'wrap real current elt');# test 463 } { my $t= XML::Twig->new( twig_handlers => { w => sub { $_->parent->wrap_in( 'ww'); } }) ->parse( '

text

'); is( $t->sprint, '

text

', 'wrap current elt');# test 464 } my $doc=q{]>}; my $t= XML::Twig->new->parse( $doc); (my $out= $t->sprint)=~ s{\n}{}g; is( $out, $doc, 'doc with entities but no DTD');# test 465 # test is_first(last)_child { my $t= XML::Twig->new->parse( q{}); my $root= $t->root; $root->reset_cond_cache; nok( $root->is_first_child(), 'root as first child');# test 466 nok( $root->is_last_child(), 'root as last child');# test 467 my $elt1= $root->first_child( 'elt1'); ok( $elt1->is_first_child(), 'first_child, no argument');# test 468 ok( $elt1->is_first_child( 'elt1'), 'first_child( elt1)');# test 469 nok( $elt1->is_first_child( 'elt2'), 'first_child( elt2)');# test 470 nok( $elt1->is_first_child( 'dummy'), 'first_child( dummy)');# test 471 nok( $elt1->is_last_child( ), 'last_child');# test 472 ok( $elt1->is_last_child( 'elt1'), 'last_child( elt1)');# test 473 nok( $elt1->is_last_child( 'elt2'), 'last_child( elt2)');# test 474 nok( $elt1->is_last_child( 'dummy'), 'last_child( dummy)');# test 475 } # testing alternate start tag parser { my $t=XML::Twig->new( keep_encoding => 1, parse_start_tag => sub { return ( toto => att => 1)}) ->parse( ''); is( $t->sprint, '', 'parse_start_tag');# test 476 } { my $t=XML::Twig->new( parse_start_tag => sub { return ( toto => att => 1)}) ->parse( ''); is( $t->sprint, '', 'parse_start_tag');# test 477 } # testing output_filter option { my $t= XML::Twig->new( output_filter => sub { return 'a' })->parse( ''); is( $t->sprint, 'a', 'output_filter option');# test 478 } # testing output_text_filter option { my $t= XML::Twig->new( output_text_filter => sub { return 'a' })->parse( ''); is( $t->sprint, '
', 'output_text_filter option');# test 479 } # testing id option { my $t= XML::Twig->new( id => "foo") ->parse( 'bar'); is( $t->elt_id( "f2")->sprint, 'bar', 'id option');# test 480 } # testing no_prolog option { my $t= XML::Twig->new( no_prolog => 1) ->parse( ''); is( $t->sprint, '', 'no_prolog option');# test 481 } # testing no_prolog option { my $t= XML::Twig->new( no_prolog => 1, keep_encoding => 1) ->parse( ''); is( $t->sprint, '', 'no_prolog option');# test 482 } # testing _all_ handler { my $nb_calls= 0; my $t= XML::Twig->new( twig_handlers => { _all_ => sub { $nb_calls++ } }) ->parse( 'text'); is( $nb_calls, 3, '_all_ handler');# test 483 } { my $nb_calls= 0; my $t= XML::Twig->new( start_tag_handlers => { _all_ => sub { $nb_calls++ } }) ->parse( 'text'); is( $nb_calls, 3, '_all_ handler (on starttag)');# test 484 } # test changing handlers # expressions in @exp must match the elements { my @exp= ( 'elt', 'doc/elt', '/doc/elt', 'elt[@att]', 'elt[@att="att1"]', '*[@att]', '*[@att="att1"]', '*[@att=~/att/]', 'elt[@att=~/^att/]', '_default_', 'elt[string()="toto"]', 'elt[string()=~/to/]', 'elt[string(sub)="toto"]', 'elt[string(sub)=~/to/]', ); my $doc= q{totototo totototo }; foreach my $exp (@exp) { my $res=''; my $t= XML::Twig->new( twig_handlers => { $exp => sub { $res .= "O"; }, change => sub { $res .= "C"; $_[0]->setTwigHandler( $exp => sub { $res .= "N"; }); nok( $_->closed, 'closed (on open element)');# 14 tests 485 - 498 }, doc => sub { }, # so _default_ doesnt find it sub => sub { }, }, ) ->parse( $doc); is( $res, 'OOCNN', "changing handlers on $exp");# 14 tests 499 - 512 } } { my $res=''; my $doc= q{totototo totototo totototo }; my %handlers= map { build_handler_on_att( 'O', $_) } (1..3); my $t= XML::Twig->new( twig_handlers => { %handlers, change => sub { foreach( 1..3) { $_[0]->setTwigHandler( build_handler_on_att( 'N', $_)) } }, change2 => sub { $_[0]->setTwigHandler( 'elt[@att="1"]', undef); $_[0]->setTwigHandler( build_handler_on_att( 'D', 2)); } }, ) ->parse( $doc); is( $res, 'O1O2O3N1N1N3D2', "changing handlers on atts");# test 513 sub build_handler_on_att { my( $prefix, $nb)= @_; return( qq{elt[\@att="$nb"]} => sub { $res.= $prefix . $nb }); } } { my $res=''; my $doc= q{totototo totototo totototo }; my %handlers= map { build_att_regexp_handler( 'O', $_) } (1..3); my $t= XML::Twig->new( twig_handlers => { %handlers, change => sub { foreach( 1..3) { $_[0]->setTwigHandler( build_att_regexp_handler( 'N', $_)) } }, change2 => sub { $_[0]->setTwigHandler( 'elt[@att=~ /1/]', undef); $_[0]->setTwigHandler( build_att_regexp_handler( 'D', 2)); } }, ) ->parse( $doc); is( $res, 'O1O2O3N1N1N3D2', "changing handlers on regexps on atts");# test 514 sub build_att_regexp_handler { my( $prefix, $nb)= @_; return( qq{elt[\@att=~ /$nb/]} => sub { $res.= $prefix . $nb }); } } { my $res=''; my $doc= q{totototo totototo totototo }; my %handlers= map { build_handler_on_star_att( 'O', $_) } (1..3); my $t= XML::Twig->new( twig_handlers => { %handlers, change => sub { foreach( 1..3) { $_[0]->setTwigHandler( build_handler_on_star_att( 'N', $_)) } }, change2 => sub { $_[0]->setTwigHandler( '*[@att="1"]', undef); $_[0]->setTwigHandler( build_handler_on_star_att( 'D', 2)); } }, ) ->parse( $doc); is( $res, 'O1O2O3N1N1N3D2', "changing handlers on star atts");# test 515 sub build_handler_on_star_att { my( $prefix, $nb)= @_; return( qq{*[\@att="$nb"]} => sub { $res.= $prefix . $nb }); } } { my $res=''; my $doc= q{totototo totototo totototo }; my %handlers= map { build_star_att_regexp_handler( 'O', $_) } (1..3); my $t= XML::Twig->new( twig_handlers => { %handlers, change => sub { foreach( 1..3) { $_[0]->setTwigHandler( build_star_att_regexp_handler( 'N', $_)) } }, change2 => sub { $_[0]->setTwigHandler( '*[@att=~ /1/]', undef); $_[0]->setTwigHandler( build_star_att_regexp_handler( 'D', 2)); } }, ) ->parse( $doc); is( $res, 'O1O2O3N1N1N3D2', "changing handlers on regexps on star atts");# test 516 sub build_star_att_regexp_handler { my( $prefix, $nb)= @_; return( qq{*[\@att=~ /$nb/]} => sub { $res.= $prefix . $nb }); } } { my $res=''; my $doc= q{123 113 121 }; my %handlers= map { build_string_handler( 'O', $_) } (1..3); my $t= XML::Twig->new( twig_handlers => { %handlers, change => sub { foreach( 1..3) { $_[0]->setTwigHandler( build_string_handler( 'N', $_)) } }, change2 => sub { $_[0]->setTwigHandler( 'elt[string()= "1"]', undef); $_[0]->setTwigHandler( build_string_handler( 'D', 2)); } }, ) ->parse( $doc); is( $res, 'O1O2O3N1N1N3D2', "changing handlers on elt[string()]");# test 517 sub build_string_handler { my( $prefix, $nb)= @_; return( qq{elt[string()= "$nb"]} => sub { $res.= $prefix . $nb }); } } { my $res=''; my $doc= q{123 113 121 }; my %handlers= map { build_regexp_handler( 'O', $_) } (1..3); my $t= XML::Twig->new( twig_handlers => { %handlers, change => sub { foreach( 1..3) { $_[0]->setTwigHandler( build_regexp_handler( 'N', $_)) } }, change2 => sub { $_[0]->setTwigHandler( 'elt[string()=~ /1/]', undef); $_[0]->setTwigHandler( build_regexp_handler( 'D', 2)); } }, ) ->parse( $doc); is( $res, 'O1O2O3N1N1N3D2', "changing handlers on elt[string()]");# test 518 sub build_regexp_handler { my( $prefix, $nb)= @_; return( qq{elt[string()=~ /$nb/]} => sub { $res.= $prefix . $nb }); } } # test PI and comment drops { my $doc= q{text more text}; (my $doc_without_pi = $doc)=~ s{<\?pi.*?\?>}{}g; (my $doc_without_comment = $doc)=~ s{}{}g; (my $doc_without_all = $doc)=~ s{<(\?pi|!--).*?(\?|--)>}{}g; my $t= XML::Twig->new( pi => 'drop', comments => 'process')->parse( $doc); is( normalize_xml( $t->sprint), $doc_without_pi, 'drop pis');# test 519 $t= XML::Twig->new( pi => 'process', comments => 'drop')->parse( $doc); is( normalize_xml( $t->sprint), $doc_without_comment, 'drop comments');# test 520 $t= XML::Twig->new( pi => 'drop' , comments => 'drop')->parse( $doc); is( normalize_xml( $t->sprint), $doc_without_all, 'drop comments and pis');# test 521 my $doc6=q{text more text}; $t= XML::Twig->new( pi => 'keep')->parse( $doc6); is( _hash( normalize_xml( $t->sprint)), _hash( $doc6), 'keep pi');# test 522 my $doc5=q{text more text}; $t= XML::Twig->new( pi => 'process')->parse( $doc5); is( normalize_xml( $t->sprint), $doc5, 'process pi');# test 523 my $doc4=q{text more text}; $t= XML::Twig->new->parse( $doc4); is( _hash( normalize_xml( $t->sprint)), _hash( $doc4), 'comment before PI (2 PIs, no comments)');# test 524 my $doc3=q{text more text}; $t= XML::Twig->new->parse( $doc3); is( _hash( normalize_xml( $t->sprint)), _hash( $doc3), 'comment before PI (2 PIs, no comments)');# test 525 my $doc1=q{ttext more text}; $t= XML::Twig->new->parse( $doc1); is( _hash( normalize_xml( $t->sprint)), _hash( $doc1), 'comment before PI (2 PIs, pcdata before pi)');# test 526 my $doc2=q{ text more text}; $t= XML::Twig->new->parse( $doc2); is( _hash( normalize_xml( $t->sprint)), _hash( $doc2), 'comment before PI (2 PIs)');# test 527 $t= XML::Twig->new->parse( $doc); is( _hash( normalize_xml( $t->sprint)), _hash( $doc), 'comment before PI (3 PIs)');# test 528 } # returns a string that has all the chars in the input, ordered, to allow # comparison of texts without taking the order into consideration sub _hash { return sort split //, $_[0]; } { my $doc=q{}; my $res=''; my $t= XML::Twig->new( twig_roots => { root => 1 }, start_tag_handlers => { 'elt1' => sub { $res.= 'E1'; }, 'elt2[@att="a"]' => sub { $res .= 'E2'; }, 'elt7[@att=~/b/]' => sub { $res .= 'E3'; }, '/doc/elt3' => sub { $res .= 'E4'; }, 'elt3/elt4' => sub { $res .= 'E5'; }, '*[@att="c"]' => sub { $res .= 'E6'; }, '*[@att=~/d/]' => sub { $res .= 'E7'; }, _default_ => sub { $res .= 'E0'; } }, )->parse( $doc); is( $res => 'E0E1E2E3E4E5E6E7E0', 'all types of handlers on start_tags');# test 529 } { my $doc= q{ }; my $t= XML::Twig->new( keep_spaces => 1)->parse( $doc); is( $t->sprint, $doc, 'spaces before cdata');# test 530 } { my $doc= q{ }; my $t= XML::Twig->new( keep_spaces => 1)->parse( $doc); is( $t->sprint, $doc, '2 cdata sections');# test 531 } { my $doc= q{ }; my $t= XML::Twig->new( keep_spaces => 1, comments => 'process')->parse( $doc); is( $t->sprint, $doc, 'spaces and extra data before cdata');# test 532 } { # fun with suffix and asis my $t=XML::Twig->new->parse( 'to'); $t->root->suffix( 'to'); is( $t->sprint, 'toto', 'regular suffix');# test 533 $t=XML::Twig->new->parse( 'to'); $t->root->suffix( 'to'); is( $t->sprint, 'toto', 'regular suffix needs new elt');# test 534 $t=XML::Twig->new->parse( 'to'); $t->root->suffix( '', 'asis'); is( $t->sprint, 'to', 'asis suffix needs new elt');# test 535 $t=XML::Twig->new->parse( 'to'); $t->root->suffix( '', 'asis'); is( $t->sprint, 'to', 'asis suffix');# test 536 $t=XML::Twig->new->parse( '<to/>'); $t->root->set_asis( 1); $t->root->suffix( '', 'asis'); is( $t->sprint, '', 'asis suffix (on asis elt)');# test 537 $t=XML::Twig->new->parse( '<to/>'); $t->root->set_asis( 1); $t->root->suffix( ''); is( $t->sprint, '<to/>', 'regular suffix (on asis elt)');# test 538 } { # fun with prefix and asis my $t=XML::Twig->new->parse( 'to'); $t->root->prefix( 'to'); is( $t->sprint, 'toto', 'regular prefix');# test 539 $t=XML::Twig->new->parse( 'to'); $t->root->prefix( '', 'asis'); is( $t->sprint, 'to', 'regular prefix needs new elt');# test 540 $t=XML::Twig->new->parse( 'to'); $t->root->prefix( 'to'); is( $t->sprint, 'toto', 'asis prefix needs new elt');# test 541 $t=XML::Twig->new->parse( 'to'); $t->root->prefix( '', 'asis'); is( $t->sprint, 'to', 'asis prefix');# test 542 $t=XML::Twig->new->parse( '<to/>'); $t->root->set_asis( 1); $t->root->prefix( '', 'asis'); is( $t->sprint, '', 'asis prefix (on asis elt)');# test 543 $t=XML::Twig->new->parse( '<to/>'); $t->root->set_asis( 1); $t->root->prefix( ''); is( $t->sprint, '<to/>', 'regular suffix (on asis elt)');# test 544 } { # wrap_in on the current my $t= XML::Twig->new( twig_handlers => { wrapped => sub { $_->wrap_in( wrapper => { foo => 'bar'} )} }) ->parse( 'tototata'); is( $t->sprint, 'tototata', 'wrap_in');# test 545 } { my $t= XML::Twig->new->parse( q{}); ok ( $t->first_elt( 'elt1')->has_no_atts, 'has_no_atts true');# test 546 nok( $t->first_elt( 'elt2')->has_no_atts, 'has_no_atts false');# test 547 nok( $t->first_elt( 'elt3')->has_no_atts, 'has_no_atts false');# test 548 nok ( $t->first_elt( 'elt1')->has_atts, 'has_atts false');# test 549 ok( $t->first_elt( 'elt2')->has_atts, 'has_atts true');# test 550 ok( $t->first_elt( 'elt3')->has_atts, 'has_atts true');# test 551 is( $t->first_elt( 'elt1')->att_nb, 0, 'att_nb, 0');# test 552 is( $t->first_elt( 'elt2')->att_nb, 1, 'att_nb, 1');# test 553 is( $t->first_elt( 'elt3')->att_nb, 2, 'att_nb, 2');# test 554 } { my $t= XML::Twig->new->parse( '

titi

'); $t->root->split( qr/(i)/); is( $t->sprint, '

t

i

t

i

', "split with no tag");# test 555 } { my $t= XML::Twig->new->parse( '

titi toto

'); $t->root->split( 'b'); is( $t->sprint, '

titi toto

', "split with no regexp");# test 556 } { my $t= XML::Twig->new->parse( '

titi toto

'); $t->root->split( qr/foo/, 'ta'); is( $t->sprint, '

titi toto

', 'split, no match');# test 557 } { my $doc= '

toto &ent;

'; my $t= XML::Twig->new->parse( $doc); my $alt_root= $t->root->copy; is( $alt_root->sprint, $t->root->sprint, 'copy with entity');# test 558 } { my $doc= 'toto'; my $t= XML::Twig->new->parse( $doc); my $pcdata= $t->first_elt( '#TEXT'); my $start_tag= $pcdata->start_tag; nok( $start_tag, 'start_tag for a text element');# test 559 $t->root->set_att( '#priv_att' => 1); is( $t->sprint, $doc, 'private attributes');# test 560 my $priv_elt= $t->root->insert( '#priv_elt'); is( $t->sprint, $doc, 'private element');# test 561 $priv_elt->set_gi( 'foo'); is( $t->sprint, 'toto', 'private element');# test 562 $priv_elt->set_gi( '#priv'); is( $t->sprint, $doc, 'private element');# test 563 $priv_elt->set_att( att => "val"); is( $t->sprint, $doc, 'private element');# test 564 $priv_elt->set_gi( 'foo'); is( $t->sprint, 'toto', 'private element');# test 565 } { my $doc= qq{val1val2}; my $out= qq{\n\n \n \n val1\n val2\n \n\n}; my $t=XML::Twig->new( pretty_print => 'record')->parse( $doc); is( $t->sprint, $out, 'record with empty record');# test 566 $t->set_pretty_print( 'none'); } { my $e= XML::Twig::Elt->new( 'toto'); nok( scalar $e->_is_private, 'private elt (not)');# test 567 $e->set_tag( '#toto'); ok( scalar $e->_is_private, 'private elt (yes)');# test 568 ok( scalar XML::Twig::Elt::_is_private_name( '#toto'), '_is_private_name (yes)');# test 569 nok( scalar XML::Twig::Elt::_is_private_name( 'toto'), '_is_private_name (no)');# test 570 } { my $t= XML::Twig->new->parse( ''); my $text_elt= $t->first_elt( '#TEXT'); is( $text_elt->xml_string, '', 'xml_string for cdata');# test 571 $text_elt->set_text( '<>'); is( normalize_xml( $t->sprint), ']]>', 'set_text on CDATA');# test 572 $text_elt->set_text( '<>', force_pcdata => 1); is( normalize_xml( $t->sprint), '<>', 'set_text on CDATA (with force_pcdata)');# test 573 $t->root->set_content( { att => "val" }, 'toto ', 'tata'); is( $t->root->sprint, 'toto tata', 'set_content with attributes');# test 574 $text_elt= $t->first_elt( '#TEXT'); $text_elt->set_content( 'titi'); is( $t->root->sprint, 'titi', 'set_content on text elt');# test 575 } { my $t=XML::Twig->new->parse( 'text 1text 2text 3'); my $elt1= $t->root->first_child( 'elt[1]'); my $elt2= $t->root->first_child( 'elt[2]'); my $elt3= $t->root->first_child( 'elt[3]'); my $new1= XML::Twig::Elt->new( new => "new 1"); my $new2= XML::Twig::Elt->new( new => "new 2"); my $new3= XML::Twig::Elt->new( new => "new 3"); $new1->replace( $elt1); $new2->replace( $elt2); $new3->replace( $elt3); is( $t->sprint, 'new 1new 2new 3', 'replace');# test 576 $new1->replace_with( $elt2, $elt1, $elt3); is( $t->sprint, 'text 2text 1text 3new 2new 3', 'replace');# test 577 } { if( $perl < 5.008) { skip( 1, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $doc= 'tatat more'; my $out=''; $open->( my $fh, ">", \$out); my $t= XML::Twig->new( comments => 'process', pi => 'process')->parse( $doc); $t->flush( $fh); is( $out, $doc, 'flush with cdata');# test 578 } } { my $doc=< textthis
text to 
keep spaces
  in like
    this
END my $t= XML::Twig->new( pretty_print => 'indented', keep_spaces_in => [ qw(pre) ])->parse( $doc); (my $indented= $doc)=~ s{}{\n }; is( $t->sprint, $indented, 'indented with keep_spaces_in');# test 579 $t->set_pretty_print( 'indented'); } { my $doc='text'; my $nsgmls= qq{text
\n}; my $t= XML::Twig->new( pretty_print => 'nsgmls')->parse( $doc); is( $t->sprint, $nsgmls, 'nsgmls style');# test 580 $t->set_pretty_print( 'indented'); } { my $t= XML::Twig->new->parse( 'text'); $t->root->erase; is( $t->root->sprint, "text\n", 'erase root');# test 581 } { my $t= XML::Twig->new->parse( ''); my $elt2= $t->first_elt( 'elt2'); ok( $elt2->sibling( 0, 'elt2'), 'sibling 0 (ok)');# test 582 nok( $elt2->sibling( 0, 'elt1'), 'sibling 0 (nok)');# test 583 nok( $elt2->sibling( 1, 'elt1'), 'sibling 1 (nok)');# test 584 nok( $elt2->sibling( -1, 'elt3'), 'sibling -1 (nok)');# test 585 ok( $elt2->in( 'doc'), 'in with condition');# test 586 ok( $elt2->in( $t->root), 'in with elt');# test 587 nok( $elt2->in( 'elt1'), 'in with condition (false)');# test 588 nok( $elt2->in( $t->root->last_child), 'in with elt (false)');# test 589 is( $elt2->prev_sibling( 'elt1[@att="val"]')->gi, 'elt1', '@att="val" condition');# test 590 nok( $elt2->prev_sibling( 'elt1[@att="val2"]'), '@att="val" condition (not found)');# test 591 is( $elt2->prev_sibling( 'elt1[@att=~ /val/]')->gi, 'elt1', '@att=~ /val/ condition');# test 592 nok( $elt2->prev_sibling( 'elt1[@att=~/val2/]'), '@att=~/val2/ condition (not found)');# test 593 } { if( $perl < 5.008) { skip( 2, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $out=''; $open->( my $fh, ">", \$out); my $doc='texttext'; $t= XML::Twig->new( twig_roots=> { elt2 => 1 }, start_tag_handlers => { elt => sub { print $fh ''; } }, end_tag_handlers => { elt3 => sub { print $fh ''; } }, twig_print_outside_roots => $fh, keep_encoding => 1 ) ->parse( $doc); is( $out, 'texttext',# test 594 'twig_print_outside_roots, start/end_tag_handlers, keep_encoding'); close $fh; $out=''; $open->( $fh, ">", \$out); $t= XML::Twig->new( twig_roots=> { elt2 => 1 }, start_tag_handlers => { elt => sub { print $fh ''; } }, end_tag_handlers => { elt3 => sub { print $fh ''; } }, twig_print_outside_roots => $fh, ) ->parse( $doc); is( $out, 'texttext',# test 595 'twig_print_outside_roots and start_tag_handlers'); } } { my $t= XML::Twig->new->parse( 'text 1 text 2 text 3 '); my @a1= $t->get_xpath( '/doc/elt[@att="a1"]'); is( ids( @a1), 'elt-1:elt-2', 'xpath /doc/elt[@att="a1"]');# test 596 @a1= $t->get_xpath( '/doc/*[@att="a1"]'); is( ids( @a1), 'elt-1:elt-2', 'xpath /doc/*[@att="a1"]');# test 597 @a1= $t->get_xpath( '/doc//*[@att="a1"]'); is( ids( @a1), 'elt-1:elt-2', 'xpath /doc//*[@att="a1"]');# test 598 @a1= $t->get_xpath( '//*[@att="a1"]'); is( ids( @a1), 'elt-1:elt-2', 'xpath //*[@att="a1"]');# test 599 @a1= $t->get_xpath( '//elt[@att="a1"]'); is( ids( @a1), 'elt-1:elt-2', 'xpath //elt[@att="a1"]');# test 600 my @a2= $t->get_xpath( '//elt2[@id="elt2-4" and @att2="a2"]'); is( ids( @a2), 'elt2-4', 'xpath //elt2[@id="elt2-4" and @att2="a2"]');# test 601 @a2= $t->get_xpath( '//elt2[@id="toto" or @att2="a2"]'); is( ids( @a2), 'elt2-2:elt2-4:elt2-6', 'xpath //elt2[@id="toto" or @att2="a2"]');# test 602 my $a2= $t->get_xpath( '//elt2[@id="toto" or @att2="a2"]', 1); is( $a2->att( 'id'), 'elt2-4', 'xpath //elt2[@id="toto" or @att2="a2"], offset 1');# test 603 @a2= $t->get_xpath( \@a1, './elt2[@id="toto" or @att2="a2"]'); is( ids( @a2), 'elt2-2:elt2-4', 'xpath //elt2[@id="toto" or @att2="a2"] on @a1');# test 604 $a2= $t->findvalue( \@a1, './elt2[@id="toto" or @att2="a2"]'); is( $a2, 'text 1text 2', 'findvalue //elt2[@id="toto" or @att2="a2"] on @a1');# test 605 } { my $doc= qq{\n]>\ntoto &ent;\n}; my $t= XML::Twig->new( keep_encoding => 1)->parse( $doc); is( $t->sprint, $doc, 'keep_encoding with entity');# test 606 } # testing DTD parsing { my $doc= qq{\n\n]>\n}; my $t= XML::Twig->new->parse( $doc); is( $t->sprint, $doc, 'simple DTD');# test 607 } { my $doc= qq{\n\n\n]>\n}; my $t= XML::Twig->new->parse( $doc); is( $t->sprint, $doc, 'DTD 1 element and simple attlist');# test 608 } { my $doc=< ]> text DTD my $t= XML::Twig->new( ErrorContext => 1)->parse( $doc); is( $t->sprint, $doc, 'complex DTD');# test 609 is( join( ':', $t->model), 'doc:elt:elt2', 'model with no elt (all element in the dtd)');# test 610 } # testing do_not_output_DTD option { my $t= XML::Twig->new( no_prolog => 1) ->parse( ']>'); is( $t->sprint, '', 'no_prolog');# test 611 } # testing do_not_output_DTD option { my $t= XML::Twig->new( do_not_output_DTD => 1) ->parse( ']>'); is( $t->sprint, '', 'do_not_output_DTD option');# test 612 $t->purge; } # handlers on PIs { my $t= XML::Twig->new( pretty_print => 'none', twig_handlers => { '?t1' => sub { return ""; } }) ->parse( 'toto'); is( $t->sprint, 'toto', 'handler on pi t1, with comment');# test 613 } # handlers on PIs { my $t= XML::Twig->new( pretty_print => 'none', twig_handlers => { '?' => sub { return ""; } }) ->parse( 'toto'); is( $t->sprint, 'toto', 'handler on all pi, with comment');# test 614 } # creating an output encoding { if( $perl < 5.008) { skip( 1, "need perl 5.8 or above to perform these tests (you have $perl)"); } else { my $t= XML::Twig->new->parse( ''); $t->set_output_encoding( 'ISO-8859-1'); is( $t->sprint, qq{}, 'creating an output encoding');# test 615 } } # some calls that return false { my $root= XML::Twig->new->parse( '')->root; nok( $root->last_child_matches( 'toto'), 'last_child_matches (not)');# test 616 nok( $root->first_child_matches( 'toto'), 'first_child_matches(not)');# test 617 nok( $root->child_text( 1, 'toto'), 'child_text(not)');# test 618 nok( $root->child_trimmed_text( 1, 'toto'), 'child_trimmed_text(not)');# test 619 nok( $root->child_matches( 1, 'toto'), 'child_matches(not)');# test 620 nok( $root->prev_sibling_matches( 'toto'), 'prev_sibling_matches(not)');# test 621 nok( $root->prev_elt_text( 'toto'), 'prev_elt_text(not)');# test 622 nok( $root->sibling_text( 1, 'toto'), 'prev_elt_text(not)');# test 623 nok( $root->prev_elt_trimmed_text( 'toto'), 'prev_elt_trimmed_text(not)');# test 624 nok( $root->prev_elt_matches( 'toto'), 'prev_elt_matches(not)');# test 625 nok( $root->next_elt_trimmed_text( 'toto'), 'next_elt_trimmed_text(not)');# test 626 nok( $root->next_elt_matches( 'toto'), 'next_elt_matches(not)');# test 627 nok( $root->parent_text( 'toto'), 'parent_text(not)');# test 628 nok( $root->parent_trimmed_text( 'toto'), 'parent_trimmed_text(not)');# test 629 nok( $root->pcdata_xml_string, 'pcdata_xml_string of a non pcdata elt');# test 630 nok( $root->att_xml_string( 'foo'), 'att_xml_string of a non existing att');# test 631 } { my $doc=< text 1 text 2 text 1 text 2 END my $expected_doc=q{ text 1 text 2 text 1text 2}; my $expected_s1= q{ text 1 text 2 }; my $expected_s2= q{text 1text 2}; my $t=XML::Twig->new(pretty_print => 'none')->parse( $doc); is( $t->sprint, $expected_doc, 'doc with xml:space="preserve"');# test 632 is( $t->get_xpath( '//*[@id="s1"]', 0)->sprint, $expected_s1, 'sub element of an xml:space="preserve" element');# test 633 is( $t->get_xpath( '//*[@id="s2"]', 0)->sprint, $expected_s2, 'regular sub element');# test 634 } { my $e= XML::Twig::Elt->parse( ''); is( $e->xml_text, '', 'xml_text of an empty elt');# test 635 $e= XML::Twig::Elt->parse( 'toto')->first_child; is( $e->xml_text, 'toto', 'xml_text of a pcdata');# test 636 $e->set_content(); is( $e->xml_text, 'toto', 'empty set_content');# test 637 $e= XML::Twig::Elt->parse( '')->first_child; is( $e->xml_text, '', 'xml_text of a cdata');# test 638 } { my $doc= q{toto} . q{tata}; my $expected_keep= $doc; $expected_keep=~ s{toto}{foo}; $expected_keep=~ s{tata}{bar}; my $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, keep_original_prefix => 1, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); is( $t->sprint, $expected_keep, "map_xmlns and keep_original_prefix");# test 639 $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); (my $expected_remap= $expected_keep)=~ s{ns(?=\d)}{ns_}g; is( $t->sprint, $expected_remap, "map_xmlns");# test 640 } { my $doc= q{toto} . q{tata}; my $expected_keep= $doc; $expected_keep=~ s{toto}{foo}; $expected_keep=~ s{tata}{bar}; my $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, keep_original_prefix => 1, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); is( $t->sprint, $expected_keep, "map_xmlns and keep_original_prefix");# test 641 $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); (my $expected_remap= $expected_keep)=~ s{ns(?=\d)}{ns_}g; is( $t->sprint, $expected_remap, "map_xmlns");# test 642 } { my $doc= q{toto} . q{tata}; my $expected_keep= $doc; $expected_keep=~ s{toto}{foo}; $expected_keep=~ s{tata}{bar}; my $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, keep_original_prefix => 1, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); is( $t->sprint, $expected_keep, "map_xmlns and keep_original_prefix with default ns");# test 643 $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); (my $expected_remap= $expected_keep)=~ s{ns(?=\d)}{ns_}g; $expected_remap=~ s{(?sprint, $expected_remap, "map_xmlns with default ns");# test 644 } { my $doc= q{toto} . q{tatakaboom}; my $expected_keep= $doc; $expected_keep=~ s{toto}{foo}; $expected_keep=~ s{tata}{bar}; my $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, keep_original_prefix => 1, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); is( $t->sprint, $expected_keep, "map_xmlns and keep_original_prefix with default ns");# test 645 $t= XML::Twig->new( map_xmlns => { uri1 => "ns_1", uri2 => "ns_2" }, twig_handlers => { 'ns_1:elt' => sub { $_->set_text( 'foo'); }, 'ns_2:elt' => sub { $_->set_text( 'bar'); }, } ) ->parse( $doc); (my $expected_remap= $expected_keep)=~ s{ns(?=\d)}{ns_}g; $expected_remap=~ s{(?sprint, $expected_remap, "map_xmlns with default ns");# test 646 } { my $t= XML::Twig->new->parse( ''); my $elt= $t->root->insert( elt => { att => undef}); $elt->insert( '#PCDATA'); is( $t->sprint => '', "undef text and att");# test 647 } exit 0;