Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > update XML file with perl or other...?

Reply
Thread Tools

update XML file with perl or other...?

 
 
inetquestion
Guest
Posts: n/a
 
      10-07-2008
I have an XML document which I would like to modify based on the
results of a test. A subset of information contained in the XML file
is shown below. If a 'test' to each serverort were to fail, then
the xml file should be modified such that the attribute 'off' is set
to a value of 1. I was thinking of doing this in perl, but would
like to get some suggestions based on ease of modifying files, etc...
I've written some basic perl scripts to read an xml file before, but
ran into some confusion when trying to write them back out. Any
suggestions or pointers?


....
....
<app name="hokiepokie">
<instance host="server01" port="8080" Off="0"/>
<instance host="server02" port="8081" Off="0"/>
<instance host="server03" port="8082" Off="0"/>
</app>
....
....




-Inet





 
Reply With Quote
 
 
 
 
inetquestion
Guest
Posts: n/a
 
      10-07-2008
On Oct 6, 10:25 pm, inetquestion <(E-Mail Removed)> wrote:
> I have an XML document which I would like to modify based on the
> results of a test. A subset of information contained in the XML file
> is shown below. If a 'test' to each serverort were to fail, then
> the xml file should be modified such that the attribute 'off' is set
> to a value of 1. I was thinking of doing this in perl, but would
> like to get some suggestions based on ease of modifying files, etc...
> I've written some basic perl scripts to read an xml file before, but
> ran into some confusion when trying to write them back out. Any
> suggestions or pointers?
>
> ...
> ...
> <app name="hokiepokie">
> <instance host="server01" port="8080" Off="0"/>
> <instance host="server02" port="8081" Off="0"/>
> <instance host="server03" port="8082" Off="0"/>
> </app>
> ...
> ...
>
> -Inet



for example, lets say the test on server02 failed, what procedure
would need to occur to change the xml file as follows? If possible I
would prefer to do this via traditional xml methods and not text file
parsing. I'm just a little lost as to how to do it...

<app name="hokiepokie">
<instance host="server01" port="8080" Off="0"/>
<instance host="server02" port="8081" Off="1"/>
<instance host="server03" port="8082" Off="0"/>
</app>
 
Reply With Quote
 
 
 
 
xhoster@gmail.com
Guest
Posts: n/a
 
      10-07-2008
inetquestion <(E-Mail Removed)> wrote:
> I have an XML document which I would like to modify based on the
> results of a test.


You will almost certainly have to rewrite the entire file. Modifying
an XML file in place, except in some highly rigid contexts, would be quite
an adventure.


> A subset of information contained in the XML file
> is shown below. If a 'test' to each serverort were to fail, then
> the xml file should be modified such that the attribute 'off' is set
> to a value of 1. I was thinking of doing this in perl, but would
> like to get some suggestions based on ease of modifying files, etc...
> I've written some basic perl scripts to read an xml file before, but
> ran into some confusion when trying to write them back out. Any
> suggestions or pointers?


If the file isn't large compared to your RAM, I'd probably start by trying
XML::Simple, which despite the name isn't all that simple and it really
pays to read the docs pretty thoroughly.

>
> ...
> ...
> <app name="hokiepokie">
> <instance host="server01" port="8080" Off="0"/>
> <instance host="server02" port="8081" Off="0"/>
> <instance host="server03" port="8082" Off="0"/>
> </app>


Useful options for XML::Simple might be
ForceArray=>1, KeyAttr=>{app=>'name', instance=>'host'}

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
Reply With Quote
 
sln@netherlands.com
Guest
Posts: n/a
 
      10-07-2008
On Mon, 6 Oct 2008 19:46:33 -0700 (PDT), inetquestion <(E-Mail Removed)> wrote:

>On Oct 6, 10:25 pm, inetquestion <(E-Mail Removed)> wrote:
>> I have an XML document which I would like to modify based on the
>> results of a test. A subset of information contained in the XML file
>> is shown below. If a 'test' to each serverort were to fail, then
>> the xml file should be modified such that the attribute 'off' is set
>> to a value of 1. I was thinking of doing this in perl, but would
>> like to get some suggestions based on ease of modifying files, etc...
>> I've written some basic perl scripts to read an xml file before, but
>> ran into some confusion when trying to write them back out. Any
>> suggestions or pointers?
>>
>> ...
>> ...
>> <app name="hokiepokie">
>> <instance host="server01" port="8080" Off="0"/>
>> <instance host="server02" port="8081" Off="0"/>
>> <instance host="server03" port="8082" Off="0"/>
>> </app>
>> ...
>> ...
>>
>> -Inet

>
>
>for example, lets say the test on server02 failed, what procedure
>would need to occur to change the xml file as follows? If possible I
>would prefer to do this via traditional xml methods and not text file
>parsing. I'm just a little lost as to how to do it...
>
> <app name="hokiepokie">
> <instance host="server01" port="8080" Off="0"/>
> <instance host="server02" port="8081" Off="1"/>
> <instance host="server03" port="8082" Off="0"/>
></app>


Here is one approach. This avoids regenerating the entire xml file
from scratch. The raw xml is kept intact. Only the lines you pick and
modify are changed.

The capture buffers are just array's of sequence number which point to a
central data repository. The Dump function uses the sequence number
to display the raw data. Modifications are made using the sequence reference.

This will be released soon.

sln

================================================== =========

<<XML;
<!--
Notes: This xml file contains server/port information.
-->
<root>
....
....
<app name="hokiepokie">
<instance host="server01" port="8080" Off="0"/>
<instance host="server02" port="8081" Off="0"/>
<instance host="server03" port="8082" Off="0"/>
</app>
....
....
</root>
XML



# Your program.pl
# ------------

use strict;
use warnings;

use RXParse; # VERSIN 2

my $p = new RXParse();

sub starth
{
my ($obj, $el, $term, @attr) = @_;
my $buffer = lc($el);
if ($buffer eq 'instance')
{
$obj->CaptureOn ( $buffer);
}
}
sub endh
{
my ($obj, $el, $term) = @_;
my $buffer = lc($el);
if ($buffer eq 'instance')
{
$obj->CaptureOff ( $buffer, 1);
}
}

$p->setMode( 'resume_onerror'=> 1 );
$p->setHandlers ( 'start' => \&starth, 'end' => \&endh);

my $fname = 'c:\temp\hokie.xml';
open my $fh, $fname or die "can't open $fname ...";

$p->CaptureOn ( 'ALL');
my $parse_errors = $p->parse ( $fh);
$p->CaptureOff ( 'ALL');

print STDERR "Parse errors = $parse_errors\n";
close $fh;

$p->DumpCaptureBuffs (); # to view buffers


## Process the 'instance' buffer raw data. Can use rxparse built-ins if needed.
## There are many ways to do this, this is just one.
## ...


## Xml-Simple example, straight forward but not tested
#
if (0)
{
use XML::Simple;

## Get 'instance' buffer ref's to its raw data
my @instrefs = $p->GetCaptureBuffer ( 'instance'); # this function is not firm yet


## Process it
foreach my $iref (@instrefs)
{
if (defined $$iref) # In this case it will always be defined
{
my $simpref = XMLin ( $$iref, SuppressEmpty => '');
my ($host, $port, $off) = ($simpref->{host}, $simpref->{port}, $simpref->{off});

## Check the host/port status for on/off
if (1) {
$simpref->{off} = 1; # Turn it off
} else {
$simpref->{off} = 0; # Turn it on (or skip if on by default)
}
## Write it back to the instance buffer (if 'off' modified)
$$iref = XMLout ( $simpref);
}

}
## All done, write the 'all' buffer out to a file (if 'off' modified)
if (1)
{
my $fname = 'c:\temp\hokie_new.xml';
open my $fh, $fname or die "can't open $fname ...";
$p->WriteCaptureBuffer ( 'all', $fh); # this function is not firm yet.
close $fh; # can pass in file handle or ref to recieving buf.
}
}

__END__



BUFFER: instance
=====================================
index seqence
----- --------
[0] 2 <instance host="server01" port="8080" Off="0"/>
[1] 4 <instance host="server02" port="8081" Off="0"/>
[2] 6 <instance host="server03" port="8082" Off="0"/>



BUFFER: all
=====================================
index seqence
----- --------
[0] 1 <!--
Notes: The file contains server/port information.
-->
<root>
....
....
<app name="hokiepokie">

[1] -2
[2] 3

[3] -4
[4] 5

[5] -6
[6] 7
</app>
....
....
</root>

 
Reply With Quote
 
mirod
Guest
Posts: n/a
 
      10-08-2008
inetquestion wrote:
> On Oct 6, 10:25 pm, inetquestion <(E-Mail Removed)> wrote:
>> I have an XML document which I would like to modify based on the
>> results of a test. A subset of information contained in the XML file
>> is shown below. If a 'test' to each serverort were to fail, then
>> the xml file should be modified such that the attribute 'off' is set
>> to a value of 1. I was thinking of doing this in perl, but would
>> like to get some suggestions based on ease of modifying files, etc...
>> I've written some basic perl scripts to read an xml file before, but
>> ran into some confusion when trying to write them back out. Any
>> suggestions or pointers?


You could use XML::Twig. Build an XPath-like expression that matches
the element you want to update and when you reach it update the attribute.
The twig_roots/twig_print_outside_roots combo ensures that everything else gets
outputed untouched:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

# clever argument passing ;--)
my $xml = shift( @ARGV) || 'inet.xml';
my $app = shift( @ARGV) || 'hokiepokie';
my $host = shift( @ARGV) || 'server02';
my $port = shift( @ARGV) || '8081';

# the XPath expression that matches the element to update
my $trigger= qq{app[\@name="$app"]/instance[\@host="$host" and \@port="$port"]};

XML::Twig->new( twig_roots => {$trigger => \&switch_state, },
twig_print_outside_roots => 1, # everything else is untouched
)
->parsefile_inplace( $xml); # not really inplace, just looks like it

sub switch_state
{ my( $t, $instance)= @_;
$instance->set_att( Off => 1); # instance is the element object
$instance->print;
}

--
mirod
 
Reply With Quote
 
Todd Wade
Guest
Posts: n/a
 
      10-09-2008
On Oct 6, 10:25*pm, inetquestion <(E-Mail Removed)> wrote:
> I have an XML document which I would like to modify based on the
> results of a test. *A subset of information contained in the XML file
> is shown below. *If a 'test' to each serverort were to fail, then
> the xml file should be modified such that the attribute 'off' is set
> to a value of 1. * *I was thinking of doing this in perl, but would
> like to get some suggestions based on ease of modifying files, etc...
> I've written some basic perl scripts to read an xml file before, but
> ran into some confusion when trying to write them back out. *Any
> suggestions or pointers?
>
> ...
> ...
> <app name="hokiepokie">
> * * <instance host="server01" port="8080" Off="0"/>
> * * <instance host="server02" port="8081" Off="0"/>
> * * <instance host="server03" port="8082" Off="0"/>
> </app>
> ...
> ...
>
> -Inet


Here is a way to do it using the XML::XPath module:

use warnings;
use strict;
use XML::XPath;

my $document = XML::XPath->new( xml => join('', <DATA>) );
my $query = '/app/instance';
my $instances = $document->find($query);

foreach my $instance ( $instances->get_nodelist ) {
my $host = $instance->findvalue('./@host');
my $port = $instance->findvalue('./@port');

# conditional to decide if you want to change the Off attribute
if ( $host eq 'server02' ) {
$instance->getAttributeNode('Off')->setNodeValue(1);
}
}

print $document->findnodes_as_string('/');

__DATA__
<app name="hokiepokie">
<instance host="server01" port="8080" Off="0"/>
<instance host="server02" port="8081" Off="0"/>
<instance host="server03" port="8082" Off="0"/>
</app>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Update On The Windows Phone 7 Update Update Lawrence D'Oliveiro NZ Computing 2 02-25-2011 08:03 AM
FAQ 1.4 What are Perl 4, Perl 5, or Perl 6? PerlFAQ Server Perl Misc 0 01-23-2011 05:00 AM
Problem to insert an XML-element by XSLT-converting from one XML-file into another XML-file jkflens XML 2 05-30-2006 09:41 AM
Different results parsing a XML file with XML::Simple (XML::Sax vs. XML::Parser) Erik Wasser Perl Misc 5 03-05-2006 10:09 PM
Perl Help - Windows Perl script accessing a Unix perl Script dpackwood Perl 3 09-30-2003 02:56 AM



Advertisments