Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

XML::XPath

by Anonymous Monk
on Aug 18, 2003 at 22:17 UTC ( [id://284743]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hey all, Anyone have any suggestions as to how to remove a child node using XML::XPath? I have the following XML file
<blah> <datarec> <filename>blah</filename> <filename>blah2</filename> </datarec> </blah>
My end goal is to actually replace the filenames blah and blah2 with an undetermined list ie maybe more, maybe less, of different filenames. I figured stripping out the filenames and then doing a glob of the files and then using appendChild to readd each of the child nodes using XML::XPath would do. Is this conceptually sane or is there some better way to do it?

Replies are listed 'Best First'.
•Re: XML::XPath
by merlyn (Sage) on Aug 18, 2003 at 23:25 UTC
    You might look into XML::XSH, which allows you to specify algorithmic parsings and changes of XML using a hybrid of Perl and an "XSH" language. For example, this XSH script would remove your existing filename records, and replace them with the names of the files in the current directory:
    open mydoc="thedoc.xml" cd //filename/.. rm filename foreach { glob("*") } { insert element filename into . insert text $__ into filename[last()] } save mydoc
    I'm working on getting my head around it enough to write an upcoming magazine article or two.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: XML::XPath
by BrowserUk (Patriarch) on Aug 19, 2003 at 00:46 UTC

    If you look into the t\* directory that comes with XML::XPath, you'll find a test script called remove.t.

    This shows a method, $root->removeChild($nodes[0]);.

    That said, I looked through all the documentation I could find and scanned all the obvious looking source files and failed to find any documentation on the method, nor even where it is implemented?

    Maybe it's so intuative to use that it doesn't require documenting.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      XML::XPath has been in maintainence mode for a long time now. That means I'm not changing or fixing the API (much) and I'm not doing any personal work on it (if you want a more complete DOM + XPath module look to XML::LibXML). If anyone wants things fixed (like documentation) they're going to have to send patches, sorry.

        No apoligies necessary, my comments weren't intended as critisism, just a note of the situation as I found it and an attempt to take the sting away from the OP who had failed to find the removeChild() call, which is indeed, fairly self-expanatory once you know it's there.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
        If I understand your problem, I can solve it! Of course, the same can be said for you.

Re: XML::XPath
by dishwasher179 (Initiate) on Aug 19, 2003 at 01:55 UTC
    Hey all, I ended up using XML::Twig for removing and re-adding the appropriate filenames. My code looks something like this:
    my $t = new XML::Twig( ignore_elts => {'/bxh/datarec/filename' => 1, '/bxh/datarec/fileoffset' => 1, '/bxh/datarec/filerecordsize' => 1, }, TwigHandlers => { '/bxh/datarec' => \&add_filenames, }, pretty_print=>'indented', ); $t->parsefile($file); # build it $t->print; # output the twig sub add_filenames { my($t,$drec) = @_; my @filenames = glob "mri*.img"; foreach my $file(@filenames) { my $elt = new XML::Twig::Elt('filename',$file); $elt->paste('last_child',$drec); my $size = -s $file; $elt = new XML::Twig::Elt('fileoffset','0'); $elt->paste('last_child',$drec); $elt = new XML::Twig::Elt('filerecordsize',$size); $elt->paste('last_child',$drec); } }
    Thanks for everyone's input!

      Interesting, I had never thought about using ignore_elts to effectively delete elements. That's smart though. You just have to be sure that you don't ever have any other element in datarec. I would maybe add an extra $drec->cut_children at the beginning of add_filename, just in case. Fixed formats seem to have a natural tendency to evolve over time. ;--(

      You could get a slightly shorter, and I think nicer looking code, by using the insert_new_elt method:

      $elt = new XML::Twig::Elt('fileoffset','0'); $elt->paste('last_child',$drec);

      becomes:

          $drec->insert_new_elt( last_child => 'fileoffset', '0');

Log In?
Username:
Password:

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

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

    No recent polls found