问题
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!
回答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
回答2:
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');
来源:https://stackoverflow.com/questions/41850778/copy-data-inside-one-field-xml