0

I would like to replace specific values (Not for all elements). Here all are having same Background_color, but i do not want to replace Background_color for only specific one. How can we implement? This is just a sample code.(I would have list of skin names in file for which i should not replace the Background_color)

            <Skins>
             <skin>
               <att name="Name" value="sknLblG3S3" type="String"/>
               <att name="WidgetType" value="Label" type="String"/>
               <att name="Background_color" value="228,221,213" type="RGB"/>
            <skin>
            <skin>
              <att name="Name" value="name" type="String"/>
              <att name="WidgetType" value="Label" type="String"/>
              <att name="Background_color" value="228,221,213" type="RGB"/>
            <skin>
            <skin>
              <att name="Name" value="sknLblG3S5" type="String"/>
              <att name="WidgetType" value="Label" type="String"/>
              <att name="Background_color" value="228,221,213" type="RGB"/>
            <skin>
            <skins>
3
  • I would like to iterate through the whole xml file. Commented Nov 19, 2015 at 9:08
  • 1
    What you tried so far? Commented Nov 19, 2015 at 10:52
  • Whilst I'm normally keen on people trying to do it themselves, when it comes to XML that's often going off in completely the wrong direction anyway, and trying to hack it with regular expressions. Commented Nov 19, 2015 at 11:48

2 Answers 2

1

Assuming your XML is in fact valid (your sample isn't - I've had to fix some of the tags by hand) - Then you should use an XML parser. As you've tagged perl, I'll assume a perl answer is acceptable:

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;

my $twig = XML::Twig->parsefile( 'your_file.xml' );

#find and iterate all the 'skin' elements. 
foreach my $skin ( $twig->get_xpath('//skin') ) {
    #Check the 'att' element with these particular attributes. E.g. Name, sknLblG3S3
    if ( $skin->get_xpath('./att[@name="Name"][@value="sknLblG3S3"]') ) {
        #select the att with a name of 'Background_Colour' 
        my $bg_att = $skin->get_xpath( './att[@name="Background_color"]', 0 );
        #modify the attribute 'value'. 
        $bg_att->set_att( 'value', "123,456,789" );
    }
}

#set output formatting - note, this can break with certain XML elements, which you don't seem to have. 
$twig->set_pretty_print('indented');
$twig->print;

You could iterate the att elements with $skin -> children() if you find it easier to read, and the att method in XML::Twig reads attributes. I feel xpath is clearer in this example though.

(You can also probably do a more complicated xpath statement to match children/siblings, but I'm not sure that'd help readability).

Sign up to request clarification or add additional context in comments.

2 Comments

Actually this is what our xml file would like, (We are using this for our mobile based applications). Its just that I have reduced the number of att tags. xml file is one file and another file for having names of some specific skin names. So how do i take the name for another file and compare if this name is the one in loop??
That's an entirely different question, and you should probably ask it separately. But do double check if your XML is valid in your source sample - because what you quoted isn't.
0

In awk, you could try this

awk -F"=?\"?[ ]*" 'BEGIN{replace="sknLblG3S3"; newcolor="0,0,0"}
                   $4=="Name"{name=$6}
                   ($4=="Background_color" && match(replace, name))
                      {gsub(/value="[0-9,]*"/, "value=\""newcolor"\"");}
                   {print;}' inputFile

You have to define two variables in the BEGIN-block:

  • replace: The skin name(s) to be replaced, e.g., replace="name,sknLblG3S3"
  • newcolor: The new background color

1 Comment

... but you really shouldn't, because regex based parsing of XML is a filthy habit.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.