#!/usr/bin/perl -w 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 $TMAX=96; print "1..$TMAX\n"; { my $d="titlep 1 p 2"; is( lf_in_t( XML::Twig->parse( pretty_print => 'indented', discard_spaces => 1, $d)), 1, 'space prevents indentation'); is( lf_in_t( XML::Twig->parse( pretty_print => 'indented', discard_all_spaces => 1, $d)), 5, 'discard_all_spaces restores indentation'); } sub lf_in_t { my($t)= @_; my @lfs= $t->sprint=~ m{\n}g; return scalar @lfs; } { my $d=''; my @tests= ( [ 't1|t2', HN => 't1t2' ], [ 't1|t2|t3[@att="a|b"]', HN => 't1t2t3-1' ], [ 't1|t2|t3[@att!="a|b"]', HN => 't1t2t3-2t3-3' ], [ 't1|level(1)', H => 't1t1t2t3-1t3-2t3-3' ], [ 't1|level(2)', H => 't1t4' ], [ 't1|_all_', H => 't1t1t2t3-1t3-2t4t3-3d'], [ qr/t[12]/ . '|t3/t4', H => 't1t2t4' ], [ 't3[@a2="a|b"]', HN => 't3-2' ], [ 't3[@a2="a|b"]|t3|t3/t4', H => 't3-1t3-2t3-2t4t3-3' ], ); foreach my $test (@tests) { my $nb=0; my $ids=''; my( $trigger, $test_cat, $expected_ids)= @$test; my $handlers= $test_cat =~ m{H} ? { $trigger => sub { $ids.=$_->id; 1; } } : {}; my $t= XML::Twig->new( twig_handlers => $handlers )->parse( $d); is( $ids, $expected_ids, "(H) trigger with alt: '$trigger'"); my $uniq_ids= join '', sort $expected_ids=~m{(t\d(?:-\d)?)}g; if( $test_cat =~ m{X}) { (my $xpath= "//$trigger")=~ s{\|t}{|//t}g; is( join( '', map { $_->id } $t->findnodes( $xpath)), $uniq_ids, " (X) path with |: '$trigger'"); } if( $test_cat =~ m{N}) { is( join( '', map { $_->id } $t->root->children( $trigger)), $uniq_ids, "(N)navigation with |: '$trigger'"); } } } { my $t1= XML::Twig->parse( ''); is( XML::Twig->active_twig()->root->id, 'd1', 'active_twig, one twig'); my $t2= XML::Twig->parse( ''); is( XML::Twig->active_twig()->root->id, 'd2', 'active_twig, second twig'); } { eval { XML::Twig->new(error_context => 1)->parse( $0); }; matches( $@, "you seem to have used the parse method on a filename", 'parse on a file name'); } { my $got; XML::Twig->parse( twig_handlers => { 'e[@a]' => sub { $got .= $_->id; } }, ''); is( $got, 'i1i3', 'bare attribute in handler condition'); } { my $doc= q{]>&ext;}; ok( XML::Twig->parse( expand_external_ents => -1, $doc), 'failsafe expand_external_ents'); } { my $t=XML::Twig->parse( q{e11e21e12}); is( join( ':', $t->findvalues( [$t->root->children], "./e1")), 'e11:e12', 'findvalues on array'); } { my $t=XML::Twig->parse( ""); $t->set_encoding( "UTF-8"); is( $t->sprint, qq{\n}, 'set_encoding without XML declaration'); } { my $t=XML::Twig->parse( ""); $t->set_standalone( 1); is( $t->sprint, qq{\n}, 'set_standalone (yes) without XML declaration'); } { my $t=XML::Twig->parse( ""); $t->set_standalone( 0); is( $t->sprint, qq{\n}, 'set_standalone (no) without XML declaration'); } { my $t=XML::Twig->parse( ""); nok( $t->xml_version, 'xml_version with no XML declaration'); $t->set_xml_version( 1.1); is( $t->sprint, qq{\n}, 'set_xml_version without XML declaration'); is( $t->xml_version, 1.1, 'xml_version after being set'); } { my $t= XML::Twig->new; is( $t->_dump, "document\n", '_dump on an empty twig'); } { my $t=XML::Twig->parse( pretty_print => 'none', 'foobar'); $t->root->field_to_att( 'f[@a="b"]', 'g'); is( $t->sprint, 'foo', 'field_to_att on non-simple condition'); $t->root->att_to_field( g => 'gg'); is( $t->sprint, 'barfoo', 'att_to_field with att != field'); } { my $t=XML::Twig->parse( ''); $t->root->wrap_in( 'nroot'); is( $t->sprint, '', 'wrapping the root'); } { my $t=XML::Twig->new; XML::Twig::_set_weakrefs(0); my $doc='\n texttext more text foo\n more'; $t->parse( $doc); $doc=~ s{\n }{}; # just the first one is( $t->sprint, $doc, 'parse with no weakrefs'); $t->root->insert_new_elt( first_child => x => 'text'); $doc=~ s{}{text}; is( $t->sprint, $doc, 'insert first child with no weakrefs'); $t->root->insert_new_elt( last_child => x => 'text'); $doc=~ s{}{text}; is( $t->sprint, $doc, 'insert last child with no weakrefs'); $t->root->wrap_in( 'dd'); $doc=~ s{}{
}; $doc=~s{}{
}; is( $t->sprint, $doc, 'wrap with no weakrefs'); $t->root->unwrap; $doc=~s{}{}g; is( $t->sprint, $doc, 'unwrap with no weakrefs'); my $new_e= XML::Twig::Elt->new( ee => { c => 1 }, 'ee text'); $new_e->replace( $t->root->first_child( 'e')); $doc=~ s{}{ee text}; is( $t->sprint, $doc, 'replace with no weakrefs'); XML::Twig::_set_weakrefs(1); } { my $t= XML::Twig->new( no_expand => 1); XML::Twig::_set_weakrefs(0); my $doc=']> bar &bar; bar&bar;&foo; &bar; bar &foo;&bar; na &foo;'; $t->parse( $doc); (my $got= $t->sprint)=~ s{\n}{}g; is( $got, $doc, 'external entities without weakrefs'); XML::Twig::_set_weakrefs(1); } { XML::Twig::_set_weakrefs(0); { my $t= XML::Twig->new; undef $t; } ok( 1, "DESTROY doesn't crash when weakrefs is off"); XML::Twig::_set_weakrefs(1); } { my $doc= 'foobarbar'; my( $got1, $got2); XML::Twig->new( twig_handlers => { e1 => sub { $_->parent->set_att( get1 => 1); }, e2 => sub { $_->parent->set_att( '#get2' => 1); }, '[@get1]' => sub { $got1 .= 'a' . $_->id; }, '[@#get2]' => sub { $got2 .= 'a' . $_->id; }, 'e[@get1]' => sub { $got1 .= 'b' . $_->id; }, 'e[@#get2]' => sub { $got2 .= 'b' . $_->id; }, }, ) ->parse( $doc); is( $got1, 'be1ae1', 'handler on bare attribute'); is( $got2, 'be3ae3', 'handler on private (starting with #) bare attribute'); } { my $t=XML::Twig->parse( 'foo'); my $root= $t->root; ok( $root->closed, 'closed on completely parsed tree'); ok( $root->_extra_data_before_end_tag, '_extra_data_before_end_tag (success)'); nok( $root->first_child->_extra_data_before_end_tag, '_extra_data_before_end_tag (no data)'); } { my $t= XML::Twig->parse( pi => 'process', ''); is( $t->first_elt( '#PI')->pi_string, '', 'pi_string with empty data'); } { my $t= XML::Twig->parse( ''); is( ids( $t->root->children( '.a')), 'e1:f1', 'nav on class'); } { my $t=XML::Twig->parse( 'foobarfoobar123'); is ( ids( $t->root->children( 'e[string()="foo"]')), 'e1', 'navigation condition using string() ='); is ( ids( $t->root->children( 'e[string()=~/foo/]')), 'e1:e3', 'navigation condition using string() =~'); is ( ids( $t->root->children( 'e[string()!~/foo/]')), 'e2:e4', 'navigation condition using string() !~'); is ( ids( $t->root->children( 'e[string()!="foo"]')), 'e2:e3:e4', 'navigation condition using string() !='); is ( ids( $t->root->children( 'e[string()]')), 'e1:e2:e3', 'navigation condition using bare string()'); is ( ids( $t->root->findnodes( './e[string()="foo"]')), 'e1', 'xpath condition using string() ='); is ( ids( $t->root->findnodes( './e[string()=~/foo/]')), 'e1:e3', 'xpath condition using string() =~'); is ( ids( $t->root->findnodes( './e[string()!~/foo/]')), 'e2:e4', 'xpath condition using string() !~'); is ( ids( $t->root->findnodes( './e[string()!="foo"]')), 'e2:e3:e4', 'xpath condition using string() !='); is ( ids( $t->root->findnodes( './e[string()]')), 'e1:e2:e3', 'xpath condition using bare string()'); is( ids( $t->root->children( 'n[string()=2]')), 'n2', 'navigation string() ='); is( ids( $t->root->children( 'n[string()!=2]')), 'n1:n3', 'navigation string() !='); is( ids( $t->root->children( 'n[string()>2]')), 'n3', 'navigation string() >'); is( ids( $t->root->children( 'n[string()>=2]')), 'n2:n3', 'navigation string() >='); is( ids( $t->root->children( 'n[string()<2]')), 'n1', 'navigation string() <'); is( ids( $t->root->findnodes( './n[string()=2]')), 'n2', 'xpath string() ='); is( ids( $t->root->findnodes( './n[string()!=2]')), 'n1:n3', 'xpath string() !='); is( ids( $t->root->findnodes( './n[string()>2]')), 'n3', 'xpath string() >'); is( ids( $t->root->findnodes( './n[string()>=2]')), 'n2:n3', 'xpath string() >='); is( ids( $t->root->findnodes( './n[string()<2]')), 'n1', 'xpath string() <'); is( ids( $t->root->findnodes( './n[string()<=2]')), 'n1:n2', 'xpath string() <='); } { my $got; my $t=XML::Twig->parse( twig_handlers => { d => sub { $got .="wrong"; }, 'd[@id]' => sub { $got .= "ok"; 0 }, }, '' ); is( $got, 'ok', 'returning 0 prevents the next handler to be called'); } { my $d=q{foo

fooblank


}; my $expected=qq{\n \n foo\n \n \n

fooblank

\n
\n
}; XML::Twig::_indent_xhtml( \$d); is( $d, $expected, '_indent_xhtml'); } { my $d='c'; my @handlers= ( '/d/e[@a="a" or @b="b"]', '/d/e[@a="a" or @b="c"]|e', '/d/e[@a="a"]', '/d/e[@b="b"]', '/d/e', 'd/e[@a="a" and @b="b"]', 'd/e[@a="a"]', 'd/e[@b="b"]', 'd/e', 'e[@a="a" or @b="b"]', 'e[@b="b" or @a="a"]', 'e[@a="a"]|f', 'e[@b="b"]', 'e', qr/e|f/, qr/e|f|g/, 'level(1)', ); my $t= XML::Twig->new(); for my $stem ( 1, 100) { my $i= $stem; my $expected= join '', ($stem..$stem+$#handlers); my $got; $t->setTwigHandlers( { map { $_ => sub { $got .= $i++; } } @handlers }); $t->parse( $d); is( $got, $expected, 'handler order'); } } { my $t=XML::Twig->parse( ""); $t->{twig_dtd}=""; is( $t->doctype(UpdateDTD => 1), "\n", 'doctype with an updated DTD'); } { my $t=XML::Twig->parse( ''); $t->elt_accessors( 'e', 'e'); $t->elt_accessors( { e2 => 'e[2]', se => 'se', sea => 'se[@a]' }); my $root= $t->root; is( $root->e->id, 'e1', 'accessor, no alias, scalar context'); my $e2= ($root->e)[-1]; is( $e2->id, 'e2', 'accessor no alias, list context'); $e2= $root->e2; is( $e2->id, 'e2', 'accessor alias, list context'); is( $e2->se->id, 'se1', 'accessor alias, scalar context'); is( $e2->sea->id, 'se2', 'accessor, with complex step, alias, scalar context'); } { my $t=XML::Twig->new( elt_accessors => [ 'e', 'se' ]) ->parse( ''); my $root= $t->root; is( $root->e->id, 'e1', 'accessor (created in new), no alias, scalar context'); my $se= ($root->e)[-1]->se; is( $se->id, 'se1', 'accessor (created in new) no alias, scalar context, 2'); } { my $t=XML::Twig->new( elt_accessors => { e2 => 'e[2]', se => 'se', sea => 'se[@a]' }) ->parse( ''); my $e2= $t->root->e2; is( $e2->id, 'e2', 'accessor (created in new) alias, list context'); is( $e2->se->id, 'se1', 'accessor (created in new) alias, scalar context'); is( $e2->sea->id, 'se2', 'accessor (created in new), with complex step, alias, scalar context'); } { my $doc= ']>'; my $t= XML::Twig->parse( do_not_output_DTD => 1, $doc); is( $t->sprint, qq{\n}, 'do_not_output_DTD'); } { my $t= XML::Twig->parse( no_prolog => 1, ']>'); is( $t->sprint, qq{}, 'no_prolog'); } { my $t= XML::Twig->parse( ']>'); is( $t->sprint, qq{\n\n]>\n}, 'no_prolog'); } { my $e= XML::Twig::Elt->new( 'e'); $e->set_empty; is( $e->sprint, '', 'set_empty with no value'); $e->set_empty( 0); is( $e->sprint, '', 'set_empty(0)'); $e->set_empty; is( $e->sprint, '', 'set_empty with no value'); $e->set_empty( 1); is( $e->sprint, '', 'set_empty(1'); $e->set_empty; is( $e->sprint, '', 'set_empty with no value'); $e->set_empty( 1); is( $e->sprint, '', 'set_empty(1)'); my $e2= XML::Twig::Elt->parse( ''); $e2->set_not_empty(); is( $e2->sprint, '', 'set_not_empty'); ok( ! $e2->closed, 'closed on an orphan elt'); } { my $t= XML::Twig->parse( ''); my $l2= $t->first_elt( 'l2'); my $l4= $t->first_elt( 'l4'); $l2->cut; $l4->cut; is( $l4->_root_through_cut->tag, 'd', '_root_through_cut'); is( $l4->_inherit_att_through_cut( 'a', 'd'), 'd', '_inherit_att_through_cut'); } { my $s= "foo"; is( XML::Twig::_to_utf8( 'iso-8859-1', $s), $s, 'trivial test of _to_utf8'); }