leoberbert:
You can certainly do it with a regex or string substitution. But if you're going to be maintaining this and/or plan to work with more XML data, you'll really want to just learn how to work with XML. I've lately been playing with XML::Twig and find it pretty reasonable, though I still have much to learn.
So I went ahead and converted your question to an XML::Twig answer, though I had adjusted your problem a little: Specifically, I'm assuming you'll be wanting to add any number of new books to your catalog at a time. So for the input files, I used:
new_items.xml
<newitems>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
</newitems>
current_catalog.xml
<?xml version="1.0"?>
<catalog>
<book id="bk112">
<author>Galos, Mike</author>
<title>Visual Studio 7: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>49.95</price>
<publish_date>2001-04-16</publish_date>
<description>Microsoft Visual Studio 7 is explored in depth,
looking at how Visual Basic, Visual C++, C#, and ASP+ are
integrated into a comprehensive development
environment.</description>
</book>
</catalog>
And the program I whipped up to merge the new items into your catalog:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my $xmlParser = XML::Twig->new();
# Fetch the new books to add to the catalog
my $new_items = fetch_xml('new_items.xml');
my @add;
for my $book ($new_items->root->children('book')) {
push @add, $book->copy();
}
print scalar(@add), " new books to add to the catalog!\n";
# Add the books to the catalog
my $cur_catalog = fetch_xml('current_catalog.xml');
for my $book (@add) {
# Each book will be added after the last book in the catalog
$book->paste(last_child => $cur_catalog->root);
}
# Now dump our current catalog
$cur_catalog->flush( \*STDERR, pretty_print=>'indented' );
sub fetch_xml {
my $fname = shift;
my $txt = do {
open my $FH, '<', $fname or die "$fname: $!";
local $/;
<$FH>;
};
$xmlParser->parse($txt);
return $xmlParser;
}
Which (when run on my machine) gives:
$ perl ex_XML_merge_twig.pl
1 new books to add to the catalog!
<?xml version="1.0"?>
<catalog>
<book id="bk112">
<author>Galos, Mike</author>
<title>Visual Studio 7: A Comprehensive Guide</title>
<genre>Computer</genre>
<price>49.95</price>
<publish_date>2001-04-16</publish_date>
<description>Microsoft Visual Studio 7 is explored in depth,
looking at how Visual Basic, Visual C++, C#, and ASP+ are
integrated into a comprehensive development
environment.</description>
</book>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
</catalog>
I originally tried to have two XML documents open and copy/paste items from one into the other, but my XML::Twig-fu isn't adequate. So I opted to build an array of books copied out of the first one, then paste the copies into the new document. I'll have to bone up a bit more on XML::Twig to see how to process multiple documents at once. But this should hopefully get you off to a good start in XML whacking after you tire of the "fun" of regexes and string manipulation.
...roboticus
When your only tool is a hammer, all problems look like your thumb.