tags:

views:

734

answers:

5

I have an XML file with the following line:

            <VALUE DECIMAL_VALUE="0.2725" UNIT_TYPE="percent"/>

I would like to increment this value by .04 and keep the format of the XML in place. I know this is possible with a Perl or awk script, but I am having difficulty with the expressions to isolate the number.

A: 

Something akin to the following will work. It may need tweaking if there is extra spacing, but that is left as an exercise for the reader.

function update_after(in_string, locate_string, delta) {
    local_pos = index(in_string,locate_string);
    leadin    = substr(in_string,0,local_pos-1);
    leadout   = substr(in_string,local_pos+length(locate_string));
    new_value = leadout+delta;
    quote_pos = index(leadout,"\"");
    leadout   = substr(leadout, quote_pos + 1);
    return leadin locate_string new_value"\"" leadout;
}

/^ *\<VALUE/{
    print  update_after($0, "DECIMAL_VALUE=\"",0.4);
}
Richard Harrison
+4  A: 

If you're on a box with the xsltproc command in place I would suggest you use XSLT for this.

For a Perl solution I'd go for using the DOM. Check this DOM Processing with Perl article out.

That said. If your XML file is produced in a predictable way something naïve like the following could work:

perl -pe 's#(<VALUE DECIMAL_VALUE=")([0-9.]+)(" UNIT_TYPE="percent"/>)#"$1" . ($2 + 0.4) . "$3"#e;'
PEZ
I think you mean "($2 + 0.4)" not "($2 * 0.4)".
j_random_hacker
Yeah, stupid me. I'll fix that right away.
PEZ
+2  A: 

This takes input on stdin, outputs to stdout:

while(<>){
 if( $_ =~ /^(.*DECIMAL_VALUE=\")(.*)(\".*)$/ ){
  $newVal = $2 + 0.04;
  print "$1$newVal$3\n";
 }else{
  print $_;
 }
}
Colin
+3  A: 
mirod
Hey, I've been working in projects that relies heavily on Twig. Belated thanks for writing such an excellent module!
PEZ
Thanks.I womder if XML::Twig is to XSLT what Perl is to LISP (see http://xkcd.com/224/ )
mirod
Might be. Might be. =)
PEZ
I think you mean "$decimal_value += 0.4" not "$decimal_value *= 0.4".
j_random_hacker
Maybe that was my fault. =) Anyway, I've fixed it now.
PEZ
A: 

here's gawk

awk '/DECIMAL_VALUE/{
 for(i=1;i<=NF;i++){
    if( $i~/DECIMAL_VALUE/){
        gsub(/DECIMAL_VALUE=|\042/,"",$i)
        $i="DECIMAL_VALUE=\042"$i+0.4"\042"
    }
 }
}1' file
ghostdog74