in reply to inserting a tag before a string
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.xmlcurrent_catalog.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>
<?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.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: inserting a tag before a string (XML::Twig) -- oneliner
by Discipulus (Canon) on Nov 30, 2017 at 22:16 UTC |