I need to change some xml data, and I'm stuck trying to identify the node to modify, so hoping someone can dispel my ignorance.
This is a sample of the xml data file ('n4000-small.xml'); the real data has many matrix elements, not just two, and has siblings of the vm elements:
<formation name="stoneridge" version="1.6">
<block>
<matrix>
<vm type="sns">
<release version="8.5.e">
<supported>
<fixed>123.1106</fixed>
</supported>
</release>
</vm>
<vm type="br">
<release version="7.2.2">
</release>
</vm>
</matrix>
<matrix>
<vm type="sns">
<release version="4.1.e">
<supported>
<min>124.1306</min>
<max>124.1500</max>
</supported>
</release>
</vm>
<vm type="br">
<release version="7.2.1">
</release>
</vm>
</matrix>
</block>
</formation>
I need to locate the 'matrix' node which has a 'vm' node of 'type="br"' with a specific 'release version' attribute value, then change that matrix's 'vm type="sns"' values (more on that below). I can't figure out what's wrong with my code:
use strict;
use warnings;
use XML::LibXML;
my $file = 'n4000-small.xml';
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($file);
# THIS WORKS - but it's finding the vm node not the matrix node
foreach my $vm ($doc->findnodes('//vm[@type=\'br\']')) {
print "br ", $vm->findvalue("./release/\@version"), "\n";
if ( '7.2.1' eq $vm->findvalue("./release/\@version")) {
print "found 7.2.2\n"
}
}
# this also works, finding the "br" vm with the right version, but I t
+hink I need the matrix, to identify the "sns" vm
my @wanted_vm = ($doc->findnodes('//vm[@type=\'br\' and ./release/@ve
+rsion=\'7.2.1\']'));
if( @wanted_vm ) {
print "found br ", $wanted_vm[0]->findvalue('./release/@version'),
+ "\n";
}
# this gets the 'br' matrices, but why doesn't it get the vm attribute
+s?
foreach my $matrix ($doc->findnodes( '//matrix/vm[@type=\'br\']' )) {
if( $matrix ) {
#print "matrix:", $matrix->toString(), "\n";
print "vm release version:", $matrix->findvalue('./vm/release/
+@version'), "\n";
my $vm_type = $matrix->findvalue('./vm/@type');
print "vm type:'" . $vm_type . "'" . "\n";
}
}
Given that 'matrix' is parent of 'vm', can some kind, wiser monk please say why xpath './release/@version' of a vm node works, but './vm/release/@version' xpath from a matrix node does not? (I'm not certain this is the right terminology, but hope it's understandable.)
I haven't got as far as changing the "sns" vm's data yet. There will be two things to do: (i) change the value of the sns vm's 'release version' attribute; and (ii) either change the '//supported/fixed' element's text, or if there are '//supported/max' and '//supported/min' elements they must be removed and replaced by a '//supported/fixed' element with given text. Any gestures in those directions (especially on how to add the 'fixed' element) will also be very helpful and much appreciated.