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.


In reply to xpath problem using XML::LibXML by anadem

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.