0

I have some lines like:

<channel update="i" site="merge-xmltv" site_id="" xmltv_id="Rai 1">Rai 1</channel>
<channel update="i" site="merge-xmltv" site_id="" xmltv_id="Rai 1 +2HD">Rai 1 +2HD</channel>
<channel update="i" site="merge-xmltv" site_id="" xmltv_id="Rai 1 +1HD">Rai 1 +1HD</channel>

I need copy the value of xmltv_id into site_id like this:

<channel update="i" site="merge-xmltv" site_id="Rai 1" xmltv_id="Rai 1">Rai 1</channel>
<channel update="i" site="merge-xmltv" site_id="Rai 1 +2HD" xmltv_id="Rai 1 +2HD">Rai 1 +2HD</channel>
<channel update="i" site="merge-xmltv" site_id="Rai 1 +1HD" xmltv_id="Rai 1 +1HD">Rai 1 +1HD</channel>

I was thinking to use SED but I am in the trouble.

Thank you in someone want help me!

Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60

2 Answers2

1

As Ruslan Osmanov pointed out, the tool for this kind of job is xmlstarlet. The most obvious solution would be:

xmlstarlet ed -u "//channel/@site_id" -x "../@xmltv_id" input

However, that does not seem to work in my version of xmlstarlet. You can work around the problem, however:

xmlstarlet ed -u "//channel/@site_id" -x "string(../@xmltv_id)" input
Michael Vehrs
  • 3,293
  • 11
  • 10
0

Don't use sed. It's the wrong tool for the job. XML is contexual, and regular expressions are not.

Perl can do it, with an XML parsing library (I like XML::Twig).

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

#load your XML
my $twig = XML::Twig -> new;
   $twig -> parsefile ('test3.xml'); 

#iterate all 'channel' nodes. 
foreach my $channel ( $twig -> get_xpath('//channel') ) {
     #replace a blank site ID
    if ( $channel -> att('site_id') eq "" ) {
       #with the content of xmltv_id attribute
       $channel -> set_att('site_id', $channel->att('xmltv_id'));
    }
}

$twig -> set_pretty_print('indented');
$twig -> print;

This reads your file, and prints the changed file to 'stdout', so you can verify it.

If you're feeling a bit more bold, you can use parsefile_inplace - but note, you should be a bit more careful about this, because you can clobber your original file:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig -> new ( pretty_print => 'indented_a',
                              twig_handlers => { 
                                'channel' => sub { 
                                    $_ -> set_att('site_id', $_->att('xmltv_id')); 
                                    $_ -> flush }
                              } ) -> parsefile_inplace('test3.xml');
Sobrique
  • 52,974
  • 7
  • 60
  • 101
  • I tried your solution but I am using CGWIN and I can't use Twig :( :( – Tapiocapioca Jan 26 '17 at 09:13
  • Strawberry perl has it bundled. Which is what I use on Windows. But 'inplace edit' doesn't necessarily work quite as well due to windows file locking, so printing to a (new) file and renaming is probably the way to go. – Sobrique Jan 26 '17 at 09:43