in reply to Re: XML Search and Replace
in thread XML Search and Replace

I'll test the above after I post this sample Data. The problem here is this sample data while fine for 'an' example is not indicitive of each XML that may need to be processed. This script is part of a familiy of deployment scripts that deploy applications to various servers. Each deployment might reference a different set of servers and the XML tree may be completely different.

This had previously been done via a name=value pairs in a user supplied configuration file and a script would go through a flat(property)file, find the name and substitue the supplied value. Then someone decided it would be better if the property files that were being updated would be in XML.

Here a sample file:

<ImageQuery547> <root> <TraceNumQuery> <Path>http://localhost:8080/image/ImageVendorServlet?</Pat +h> <TraceNum>trace</TraceNum> <Date>dt</Date> <Face>fb </Face></TraceNumQuery> <CheckNumQuery> <Path>http://666.666.210.72/wetest/we.dll?</Path> <Account>acct</Account> <Amount>amt</Amount> <CheckNum>sn</CheckNum> <Date>dt</Date> <Face>fb</Face> <Ping>ping</Ping> </CheckNumQuery></root> </ImageQuery547>

Typically the values of the Paths (Servers) would be changed on each deployement. This creates the problem of identifying a <TraceNumQuery><Path> from a <CheckNumQuery><Path> and inserting the correct values.

In this case what I would like to is pick up (from a flat file config file ) $filename $element (this could be in the form of "TraceNumQuery::Path" and $value ("http://foo.bar:8080/baz"), and substitue it for the value currently at TraceNumQuery::Path" (http://localhost:8080/image/ImageVendorServlet?)

coreolyn (Should've supplied this right away doh!)

Replies are listed 'Best First'.
Re: Re: Re: XML Search and Replace
by mirod (Canon) on Jun 11, 2002 at 18:00 UTC

    So here is how I would do it: you only need to update this one tag (possibly many times in the file), so I would use twig_roots and twig_print_outside_roots here: you just go through the file, outputting it as-is unless you find the path, in which case you use a handler to change the content of the element. This will give you the minimum memory footprint (and it's pretty simple too!).

    Call this as update file.xml TraceNumQuery/Path http://foo.bar:8080/baz

    #!/usr/bin/perl -w use strict; use XML::Twig; my $USAGE= "$0 <file> <path_to_update> <value>"; die $USAGE unless( @ARGV == 3); my( $file, $path, $value)= @ARGV; # $_ is set to the current element in the handler # you could also delete the element after printing it # for even less memory usage my $twig= XML::Twig->new( twig_roots => { $path => sub { $_->set_text( + $value); $_->print; } }, twig_print_outside_roots => 1, ); $twig->parsefile( $file);

      Sweetness! Very cool. Thanks to everyone who muddled through trying to help me. This will do it!

      coreolyn