use strict; use XML::Rules; my $xr = XML::Rules->new( stripspaces => 15, rules => { '^ShippingChargesCollection' => 'skip', # skip the ... TaxableLocation => sub { my ($tag, $attr) = @_; return if $attr->{locationType} ne 'state'; # ignore other location types return '@states' => $attr->{locationValue}; # push the state into the data of the parent tag }, TaxableLocationsCollection => 'pass no content', # dissolve the TaxableLocationsCollection, ignore text content Seller => 'pass', # dissolve the tag SellerInformation => sub { my ($tag, $attr) = @_; return $attr->{sellerIdFromProvider} => {name => $attr->{_content}, states => $attr->{states}}; # sellerIdFromProvider and _content comes from the dissolved # states is an array that comes from # use the id as the hash key }, 'DataFeed' => sub { delete $_[1]->{recordCount}; return $_[1]} # ignore the recordCount attribute, return the data from SellerInformation }); my $data = $xr->parsefile($filename); use Data::Dumper; print Dumper $data;