$xml = <<'*END*'; Jane Luser JLuser@bogus.com
Washington st. Old Creek The US bleargh
123-456-7890 663-486-7890 663-486-7000
John Other JOther@silly.com
Grant's st. New Creek Canada sdrysdfgtyh degtrhy degtrhy werthywerthy drthyu
663-486-7891
*END* %rules = ( _default => 'content', bogus => undef, # means "ignore" address => sub {address => "$_[1]->{street}, $_[1]->{city} ($_[1]->{country})"}, person => sub { '@person' => "$_[1]->{lname}, $_[1]->{fname}\n<$_[1]->{email}>\n$_[1]->{address}" }, doc => sub { join "\n\n", @{$_[1]->{person}} }, ); # $parser->parse() will return a single string containin the addresses # in plain text format %rules = ( _default => 'content', # bogus => sub {}, # means "returns no value. The subtags ARE processed. bogus => undef, # means "ignore". The subtags ARE NOT processed. address => 'no content', person => 'no content array', doc => sub {$_[1]->{person}}, #'pass no content', foo => sub {print "FOOOOOOOO\n"}, ); # returns a simplified data structure kinda similar to XML::Simple my $parser = new XML::Rules ( rules => [ _default => sub {$_[0] => $_[1]->{_content}}, 'fname,lname' => sub {$_[0] => $_[1]->{_content}}, bogus => undef, address => sub {address => "$_[1]->{street}, $_[1]->{city} ($_[1]->{country})"}, phone => sub {$_[1]->{type} => $_[1]->{_content}}, # let's use the "type" attribute as the key and the content as the value phones => sub {delete $_[1]->{_content}; %{$_[1]}}, # remove the text content and pass along the type => content from the child nodes person => sub { # lets print the values, all the data is readily available in the attributes print "$_[1]->{lname}, $_[1]->{fname} <$_[1]->{email}>\n"; print "Home phone: $_[1]->{home}\n" if $_[1]->{home}; print "Office phone: $_[1]->{office}\n" if $_[1]->{office}; print "Fax: $_[1]->{fax}\n" if $_[1]->{fax}; print "$_[1]->{address}\n\n"; return; # the tag is processed, no need to remember what it contained }, ] ); # prints the addresses, returns nothing