Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Re^2: XML gurus unite!!

by vrk (Chaplain)
on Mar 05, 2007 at 12:34 UTC ( #603198=note: print w/replies, xml ) Need Help??

in reply to Re: XML gurus unite!!
in thread XML gurus unite!!

I agree, XML::Twig is great, although its API is humongous. It takes a while to find out what the correct name of the method is that you need, and they are not even sorted in any sensible way in the documentation.

XML::Twig also adheres to TIMTOWTDI. I can see two immediate ways to achieve your goal:

  1. Read in the whole XML file with

    XML::Twig->new()->parsefile('my xml file');

    then access individual nodes and change their values. (For example,

    my $twig = XML::Twig->new()->parsefile('my xml file'); # Use XPath-like expressions to find the nodes you want. my @nodes = $twig->get_xpath('attribclass/attribdef[@name="mtl_Kdiff') +; for my $node (@nodes) { # Process... # Example: $node->set_att('synthetic', 'false'); } # Or navigate through references. my @attribdefs = $twig->root->first_child('attribclass')->children('at +tribdef'); for my $node (@attribdefs) { # Process... }
  2. Create an XML filter:

    my $twig = XML::Twig->new( twig_handlers => { 'attribdef' => sub { my ($twig, $elt) = @_; if ($elt->att('name') eq 'mtl_param') { # Do something. } elsif (...) { } # etc. $twig->flush; } } )->parsefile('my xml file'); $twig->flush;

    This will read in the file, parse it, and while parsing, call the twig handlers defined above. The handlers can do their stuff (change element names, change values, cut and paste subtrees, and all other cool things), and the final XML text will be output to STDOUT ($twig->flush;).

    However, this approach is not very practical if you first need to read in some data from the file, do some processing with them, and only later go and update the file. You could first read in the file in as a data structure (almost?) identical to what XML::Simple produces:

    my $hash = XML::Twig->new()->parsefile('my xml file')->simplify(); use Data::Dumper; print Dumper($hash);

    You can then do what you like with the read values, and later use that information to construct an XML filter that will produce the final file.

This sounds more complicated than it really is. On the other hand, XML is often too complicated for its own good.

Warning: code examples not tested.

print "Just Another Perl Adept\n";

Replies are listed 'Best First'.
Re^3: XML gurus unite!!
by Mark_UpLanguage (Sexton) on Mar 05, 2007 at 15:00 UTC
    I've been down this road before, and depending on what you're trying to do another answer is to use XSLT. Now if you're not familiar with it, it certainly takes getting used to. Even when I knew it I would write a program using XML::Twig. In hindsight I've found using a simple XSLT copy template, and then adding in the templates for the cases you need is best. Additionally, the nice thing about XSLT is that you can read ahead/behind of your current node in order to pull different values together. The next level is to realize you can plug in Java functions into the namespace and get any kind of programming done. Of course none of this takes into account your memory or processing speed requirements.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://603198]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (10)
As of 2018-05-24 13:01 GMT
Find Nodes?
    Voting Booth?