I just started using Perl 1 week ago and I am a programming newbee. Please Help as my company project is relying on this.
The Situation:
I would like to open an XML file, in this example is Library.xml and edit the XML document using a specific "ISBN" number. After the ISBN number is found, I would like to change the number of pages for the particular book with the matching "ISBN" number.
The Problem:
now, I can do the above but, I need to save the updated XML with the same name "library.xml" and also maintaining the XML structure of the original XML document. This is where I am stumped. I have tried using XML::DUMPER, and XML::TWIG and may others but have failed.
The Original XML document:
The library.XML looks like this:
<library>
<book>
<title>Perl Best Practices</title>
<author>Damian Conway</author>
<isbn>0596001738</isbn>
<pages>542</pages>
<image src="http://www.oreilly.com/catalog/covers/perlbp.s.gif"
width="145" height="190" />
</book>
<book>
<title>Perl Cookbook, Second Edition</title>
<author>Tom Christiansen</author>
<author>Nathan Torkington</author>
<isbn>0596003137</isbn>
<pages>964</pages>
<image src="http://www.oreilly.com/catalog/covers/perlckbk2.s.gif"
width="145" height="190" />
</book>
<book>
<title>Guitar for Dummies</title>
<author>Mark Phillips</author>
<author>John Chappell</author>
<isbn>076455106X</isbn>
<pages>392</pages>
<image src="http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg"
width="100" height="125" />
</book>
</library>
The Code:
The following is the code I am trying to manipulate but with no success.
#!/usr/bin/perl
use strict;
use warnings;
#use XML::Simple qw(:strict);
use XML::LibXML;
use XML::Dumper;
my $dump = new XML::Dumper;
my $perl = ' ';
my $xml = $dump->pl2xml( $perl );
my $filename = 'library.xml';
my $isbn = '0596001738';
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($filename);
my $query = "//book[isbn = '$isbn']/pages/text()";
my($node) = $doc->findnodes($query);
$node->setData('99999');
$perl = $doc->toString;
$xml = $dump->pl2xml( $perl, "library.xml" );
print $doc->toString;
The Output:
The following is my output. The output does not resemble the original XML document.
<perldata>
<scalar><xml version="1.0" encoding="UTF-8">
<library>
<book>
<title>Perl Best Practices</title>
<author>Damian Conway</author>
<isbn>0596001738</isbn>
<pages>99999</pages>
<image src="http://www.oreilly.com/catalog/covers/perlbp.s.gif" width="145" height="190"/>
</book>
<book>
<title>Perl Cookbook, Second Edition</title>
<author>Tom Christiansen</author>
<author>Nathan Torkington</author>
<isbn>0596003137</isbn>
<pages>964</pages>
<image src="http://www.oreilly.com/catalog/covers/perlckbk2.s.gif" width="145" height="190"/>
</book>
<book>
<title>Guitar for Dummies</title>
<author>Mark Phillips</author>
<author>John Chappell</author>
<isbn>076455106X</isbn>
<pages>392</pages>
<image src="http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg" width="100" height="125"/>
</book>
</library>
</scalar>
</perldata>
You are mixing XML modules for no good reason - the first step in programming is understanding what you are doing, you cannot just throw code together and expect it to somehow do what you mean.
After deleting 18 lines from your program, the code looks like this and works fine:
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $filename = 'library.xml';
my $isbn = '0596001738';
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($filename);
my $query = "//book[isbn = '$isbn']/pages/text()";
my($node) = $doc->findnodes($query);
$node->setData('99999');
print $doc->toString;
The only thing missing is writing the changed document back into the file:
$doc->toFile('library.xml');
An XML::Twig solution:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
# That's probably not how you get the data
my %isbn_to_pages= ( '0596001738' => 999,
'076455106X' => 123,
);
XML::Twig->new( twig_handlers => { book => \&book },
keep_spaces => 1,
)
# the second argument creates a backup file book_data.xml.bak
->parsefile_inplace( 'book_data.xml', '.bak');
sub book
{ my( $t, $book)= @_;
my $isbn= $book->field( 'isbn');
if( my $pages= $isbn_to_pages{$isbn})
{ $_->first_child( 'pages')->set_text( $pages); }
$t->flush;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With