$|=1; use XML::Rules; $xml = <<'*END*'; <school> <classes name="Primary"> <student name="Junkman"> <Age>12</Age> </student> <student name="Lotman"> <Age>14</Age> </student> </classes> <classes name="Nursery"> <student name="Testman"> <Age>34</Age> </student> </classes> <classes name="SomeClass"> </classes> <other><tags>with values</tags></other> </school> *END* my $parser = new XML::Rules ( start_rules => [ _default => sub { if (! $_[4]->{pad}{in_interesting}) { if ($_[3]->[-1]) { print $_[3]->[-1]{_content}; delete $_[3]->[-1]{_content}; } $_[4]->{pad}{in_interesting} = 1 if ($_[0] eq 'classes'); } if (! $_[4]->{pad}{in_interesting}) { print $_[4]->toXML($_[0], $_[1], "don't close"); } return 1; } ], rules => [ _default => sub { if ($_[4]->{pad}{in_interesting}) { return [$_[0] => $_[1]] } else { print "$_[1]->{_content}</$_[0]>"; return; } }, classes => sub { my $add = $_[4]->{parameters}{$_[1]->{name}}; if ($add) { if (ref($_[1]->{_content})) { push @{$_[1]->{_content}}, @$add } else { $_[1]->{_content} = [ $_[1]->{_content}, @$add]; # there were no students in the class, the tag contained only the whitespace } } print $_[4]->toXML($_[0], $_[1]); $_[4]->{pad}{in_interesting}--; return; }, ] ); my $result = $parser->parsestring($xml, { SomeClass => [ [student => {name => 'Johny', age => {_content => 31}}], "\n", ], Nursery => [ [student => {name => 'Paul', age => {_content => 36}}], "\n", [student => {name => 'Martin', age => {_content => 33}}], "\n", ], } );