4

I have an XML file (information.xml). I have to extract element and attribute values from this XML file and insert those element and attribute values into another XML file (build.xml). I have to change the build.xml file by filling the appropriate element values and tags from information.xml file.

I have to use XML::LibXML to do so. I am able to extract the element and attribute values from information.xml. But, I am unable to open and fill those values in build.xml

Example :

information.xml

<info>
  <app version="10.5.10" long_name ="My Application">
    <name> MyApp </name>
    <owner>larry </owner>
    <description> This is my first application</description>
  </app>
</info>

build.xml

<build long_name="" version="">
  <section type="Appdesciption">
    <description> </description>
  </section>
  <section type="Appdetails">
    <app_name> </app_name>
    <owner></owner>
  </section>
</build>

Now, my task is to extract value of owner from information.xml, open build.xml, search for owner tag in build.xml and put the extracted value there.

The Perl script looks like:

#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $file1="/root/shubhra/myapp/information.xml";
my $file2="/root/shubhra/myapp/build.xml";

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($file1);
foreach my $line ($doc->findnodes('//info/app'))
{
    my $owner= $line->findnodes('./owner');  # 1st way
    print "\n",$owner->to_literal,"\n";

    my ($long_name) = $line->findvalue('./@long_name');  # 2nd way
    print "\n $long_name \n";

    my $version = $line->findnodes('@version');
    print "\n",$version->to_literal,"\n";
}

my $parser2 = XML::LibXML->new();
my $doc2 = $parser2->parse_file($file2);
foreach my $line2 ($doc2->findnodes('//build'))
{
    my ($owner2)= $line2->findnodes('./section/owner/text()');

    my ($version2)=$line2->findvalue('./@version');

    print "\n Build.xml already has version : $version2 \n";
    print "\n Build.xml already has owner :",$owner2->to_literal;

    $owner2->setData("Windows Application 2"); # Not changing build.xml
    $line2->setAttribute(q|version|,"60.60.60");  # Not changing build.xml 
    my $changedversion = $line2->getAttribute(q|version|); 
    #superficially changed but didn't changed build.xml content
    print "\n The changed version is : $changedversion";
}

build.xml looks like :

<build long_name="" version="9.10.10">
<section type="Appdesciption">
<description> </description>
</section>
<section type="Appdetails">
<app_name> </app_name>
<owner>shubhra</owner>
</section>
</build>

my $doc3 = XML::LibXML->load_xml(location => $file2, no_blanks => 1);
my $xpath_expression = '/build/section/owner/text()';
my @nodes = $doc3->findnodes( $xpath_expression );
for my $node (@nodes) {
    my $content = $node->toString;
    $content = $owner;
    $node->setData($content);
}
$doc->toFile($file2 . '.new', 1);
8
  • What have you tried? Can't you think of any DOM methods that might be useful? Perhaps you want to re-read the documentation on DOM nodes and XML elements. Commented Sep 10, 2013 at 7:19
  • I tried doing so by using findnode and findvalue option. Using findnode, I go to the particular node and using findvalue I extract the output in a variable. But, when i am trying to put that variable value in build.xml, i am unable to change the content. Commented Sep 10, 2013 at 7:32
  • 1
    OP, you need to show what you've done so we can help you. I don't see what you've been trying in terms of Perl code for the past 3 days. Commented Sep 10, 2013 at 7:32
  • Okay.wait. i will add the code here. I am making use of "setData()" to change element value. Do, I need to load the xml to actually change the content of xml file. Also, i need to make use of Xml::LIBXML only, as this is part of my old code. Commented Sep 10, 2013 at 7:39
  • 1
    Well, this is like complaining that while (<$fh>) { $_ = 42 } doesn't change the input file. The DOM is not magically tied to a file, it is a seperate in-memory representation. You have to write the document back to the file yourself, e.g. use File::Slurp; write_file "output.xml", { binmode => ':utf8' }, $doc2->toString. Commented Sep 10, 2013 at 9:41

1 Answer 1

4

The following fails to find anything (setting $owner2 to undef) since owner has no text:

my ($owner2) = $line2->findnodes('./section/owner/text()');

You want

my ($owner2) = $line2->findnodes('./section/owner');

This entails changing

print "\n Build.xml already has owner :", $owner2->to_literal;

to

print "\n Build.xml already has owner :", $owner2->textContent;

and

$owner2->setData("Windows Application 2");

to

$owner2->removeChildNodes();
$owner2->appendText("Windows Application 2");

You imply you want the following to change build.xml, but it doesn't even mention build.xml:

$line2->setAttribute(q|version|, "60.60.60");

It does modify $doc2, but you'll need to add the following code to modify build.xml too:

$doc2->toFile('build.xml');
Sign up to request clarification or add additional context in comments.

14 Comments

Thank you so much for helping and letting me know the chnages. I am new to Libxml module. But, could you please explain by example :---> why you are making use of removeChildNodes() function. What if , if I have "many nodes/elements" with the "same name" are present under one tag. Example : If I have total 3 disk's under main tag disk. Tags look like : <disks> <disk id="1"> </disk> <disk id="2"></disk> <disk id="3"> <disk> </disks>
Could you please explain!
Re "why you are making use of removeChildNodes() function.", to remove any existing text node before adding a new one.
Re "What if , if I have 'many nodes/elements' with the 'same name'", Are you asking how to extract them? my @disks = $disks->findnodes('disk'); or my @disks = $parent_of_disks->findnodes('disks/disk');
Could you please answer...appendText is not working! -ikegami
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.