Q:

Extract XML data in bash

I have a xml file that looks like this
<Module>
    <Name>VEG</Name>
      <Property Name="Carrot" Value="Orange" />
      <Property Name="Cabbage" Value="Green" />
      <Property Name="Tomato" Value="Red" />
</Module>

<Module>
    <Name>FRUITS</Name>
      <Property Name="Apple" Value="Red" />
      <Property Name="Mango" Value="Yellow" />
</Module>

How do I create an output file using Bash script so that the output looks like
VEG
  Carrot; Orange,
  Cabbage; Green,
  Tomato; Red
FRUITS
  Apple; Red,
  Mango; Yellow 

A:

@InnocentSpirit: Try:
awk '{sub(/" \/>\n<\/Module/,"",$2);gsub(/^\n| +<Name>|<\/Name>|<Property Name="|  \/>|>$/,"",$2);gsub(/" Value="/,"; ",$2);gsub(/" \/>/,",",$2);print $2} ' RS= FS="<Module>" Input_file

Adding a non-one liner form too of same, you could run it in script mode too.
awk '{
        sub(/" \/>\n<\/Module/,"",$2);
        gsub(/^\n| +<Name>|<\/Name>|<Property Name="|  \/>|>$/,"",$2);
        gsub(/" Value="/,"; ",$2);
        gsub(/" \/>/,",",$2);
        print $2
     }
    ' RS= FS="<Module>"   Input_file

Output will be as follows.
VEG
      Carrot; Orange,
      Cabbage; Green,
      Tomato; Red
FRUITS
      Apple; Red,
      Mango; Yellow

EDIT: Explanation of above code too.
awk '{
        sub(/" \/>\n<\/Module/,"",$2);                                 ## substituting pattern space /> new line then </Module> to NONE in $2, here $2(field 2) will be not usual one as I have mentioned RS equals to none and FS equal to <Module>
        gsub(/^\n| +<Name>|<\/Name>|<Property Name="|  \/>|>$/,"",$2); ## globally substituting (a line which is starting with a new line OR <Name> starting with a space OR <\/Name> OR <Property Name=" OR   \/ of $2 to NULL)
        gsub(/" Value="/,"; ",$2);                                     ## globally substituting ( Value=") to "; " in field 2.
        gsub(/" \/>/,",",$2);                                          ## gobally substituting (" \/>) to (,) in $2 only.
        print $2                                                       ## printing the new edited $2 because we have done this editing as per OP's requirement so printing the new field 2.
     }
    ' RS= FS="<Module>" file02                                         ## Mentioning RS(record separator) to NULL and FS as string <Module> and mentioning the Input_file then.

