use strict;
use XML::Rules;
my $parser = XML::Rules->new(
rules => {
_default => '',
'tags,to,keep' => 'raw',
company => sub {$_[0] => $_[1]},
},
style => 'filter',
);
$parser->filter(\*DATA);
__END__
<root>
<other><some>blah</some>foo</other>
<company>
<tags>xxx</tags>
<tags>yyy</tags>
<skip x="1">aaa</skip>
</company>
<company name="PerlSoft">
<tags>xxx</tags>
<tags>yyy</tags>
<skip x="1">aaa</skip>
</company>
</root>
Change the list of tags to keep and the name of the repeated company tag to whatever you need and you should be done ;-)
As you can see, the filtering is done only under the <company> tag, if you need to do it inside several tags, just specify their names separated by commas, just like the list of tags to accept. Keep in mind though that while processing the file the data inside each of the specified tags will be accumulated in case the rule (the anonymous subroutine) needed to make changes to it. So the contents of those tags should fit easily in memory. That's why I did not specify the subroutine rule for the root tag, but rather for the individual company.
Update: Of course you can do the insert(s)/update(s) at the same time as the filtering. You'd just have to specify what data do you want from what tag and how to include it in the datastructure being built and either copy them to the database in the rule for the company tag or even insert them once each tag that maps to a table is fully parsed and replace the data of that tag by just the ID to be used when copying the parent tag.