Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^2: XML::DOM - NOT_FOUND_ERR

by sureerat (Acolyte)
on Oct 23, 2008 at 11:43 UTC ( [id://719018]=note: print w/replies, xml ) Need Help??


in reply to Re: XML::DOM - NOT_FOUND_ERR
in thread XML::DOM - NOT_FOUND_ERR

According to my script, I would like to search each "record" node if found "institute = Thammasat" I would like to replace the "record" node with new node "$ritem". But after running the script. The result is as following: 1. The found "record" in the first employee is removed instead of replace. 2. The found "record" in the second employee is replaced correctly. Is it strange? or maybe I do something wrong. Please help. Here is the incorrect output after running script:
<?xml version="1.0" encoding="UTF-8"?> <company name="ABC" branch="bangkok"> <employee code="emp0001"> <info> <general> <name>Somchai Chaisom</name> <photo>/employee/photo/emp001.gif</photo> <position>Helpdesk Officer</position> <department>IT</department> </general> </info> <education> <record> <institute>Mahidol</institute> <year>2548-2550</year> <degree>Master</degree> <faculty>IT</faculty> <major>IT</major> <gpa>2.6</gpa> </record> </education> </employee> <employee code="emp0002"> <info> <general> <name>Manee Meena</name> <photo>/employee/photo/emp002.gif</photo> <position>Programmer</position> <department>IT</department> </general> </info> <education> <record> <institute>Siam University</institute> <year>2538-2542</year> <degree>Bachelor</degree> <faculty>Engineer</faculty> <major>Software Engineering</major> <gpa>3.3</gpa> </record> <record><institute>test</institute><degree>test</degree><g +pa>test</gpa><faculty>test</faculty><major>test</major><year>test</ye +ar></record> </education> </employee> </company>
For your question about quote and not quote the variable, I have adjust the code into the same direction as following:
#!/usr/bin/perl use warnings; use XML::DOM; $link = "Thammasat"; %rlinks = ( "institute" => "test", "year" => "test", "degree" => "test", "faculty" => "test", "major" => "test", "gpa" => "test", ); my $rfile = "employee.xml"; my $xparser = XML::DOM::Parser->new(); my $xdoc = $xparser->parsefile($rfile); $ritem = $xdoc->createElement("record"); foreach $key (keys %rlinks) { $new = $xdoc->createElement($key); $text = $xdoc->createTextNode($rlinks{$key}); $new->appendChild($text); $ritem->appendChild($new); } foreach my $xitem ($xdoc->getElementsByTagName("record")) { $durl = $xitem->getElementsByTagName("institute")->item(0)->getFir +stChild->getNodeValue; if($durl eq $link) { $p = $xitem->getParentNode(); $p->replaceChild($ritem,$xitem); #this return incorrect resu +lt #$xdoc->getDocumentElement()->replaceChild($ritem,$xitem); #t +his return NOT_FOUND_ERR } } $xdoc->printToFile($rfile);
For your comment about:
$xitem->getElementsByTagName('institute')->item(0)->getFirstChild->get +NodeValue;
It returns error after I change to: error = Can't locate object method "getNodeValue" via package "XML::DOM::NodeList"
$xitem->getElementsByTagName('institute')->getNodeValue;

Replies are listed 'Best First'.
Re^3: XML::DOM - NOT_FOUND_ERR
by Jenda (Abbot) on Oct 23, 2008 at 23:32 UTC

    The problem is that XML::DOM is a maze of objects. And each node object can only have one parent. So you first stick the <record> object in place of the first Thammasat and then MOVE the object in place of the second. You'd have to create a brand new $ritem each time you want to replace the original.

    To tell the truth, you'd most likely do better if you dumped the module and used a different. I'm surprised mirod did not already suggest his XML::Twig, anyway I'll suggest my XML::Rules:

    use strict; use XML::Rules; my $link = "Thammasat"; my $rlinks = { "institute" => ["test"], "year" => ["test"], "degree" => ["test"], "faculty" => ["test"], "major" => ["test"], "gpa" => ["test"], }; my $parser = XML::Rules->new( style => 'filter', ident => ' ', rules => { _default => 'raw extended', record => sub { return $_[0] => $_[1] unless $_[1]->{':institute'}{_conten +t} eq $link; return $_[0] => $rlinks; } }, ); $parser->filterfile('employee.xml', 'employee-filtered.xml');

    The additional advantage is that this scripts doesn't load the whole file into memory, it parses the file, copies everything outside the <record> tag and only ever remembers that single tag with contents.

      Thank you Jenda for your guideline. I can fix the problem now using XML::DOM. I'm being interested in XML::Twig and your XML::Rules, I will study both and decide again what is the best for my project. You help me a lot. Thanks again ^_^

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://719018]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (6)
As of 2024-04-23 20:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found