使用XML::LibXML和Perl查找/替换值



我在这里读过其他一些主题,但这不适合我的示例。我有一个XML文件,我想在其中查找和替换特定的值。

我的脚本正在处理预期的结果,但它非常难看,因为我没有使用模块中的所有重源。我尝试过$node->setData($content);$dom->toFile($filename),但都没有成功。

问题:目标是从媒体(XML示例的第29行第20列(中查找id,以便用$mediaIdFrom替换它,从而更好地使用不打开/关闭文件的模块。

这里是脚本:

#!/usr/bin/perl
use strict;
use warnings 'all';
use autodie;
use feature 'say';
use XML::LibXML;
my $mediaIdFrom = "MEDIAID_TEST";
my $VodItemIdFrom = "VODITEM_ID_TEST";
my $filename = 'sample.xml';
my $out_filename = $filename . ".new";
my $dom = XML::LibXML -> load_xml(location => $filename);
my $mediaId = join '', map { $_->{id}; } $dom->findnodes('/ScheduleProvider/Episode/Media');
my $vodItemId = join '', map { $_->{id}; } $dom->findnodes('/ScheduleProvider/VodItem');
if (-e $filename) {
open(IN, "<", $filename);
open(OUT, ">", $out_filename);
while (<IN>) {
chomp;
$_ =~ s/"$mediaId"/"$mediaIdFrom"/g if /$mediaId/;
$_ =~ s/"$vodItemId"/"$VodItemIdFrom"/g if /$vodItemId/;
say $_;
say OUT $_;
}
close(IN);
close(OUT);
}

这里是示例:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ScheduleProvider id="TST" name="SHOP" scheduleDate="2018-07-05T23:05:45Z">
<Product action="override" endPurchase="2018-08-04T21:59:00Z" endValidity="2018-09-05T03:31:00Z" id="TSTP937279650001" regions="Country" rentalDuration="2611920" startPurchase="2018-07-05T16:27:00Z" startValidity="2018-07-05T16:27:00Z" type="single">
<Price currency="EUR" startPurchase="2018-07-05T16:27:00Z" endPurchase="2018-08-04T21:59:00Z">0.00</Price>
<EpgDescription locale="fr_FR">
<EpgElement key="Title">NO TITLE</EpgElement>
</EpgDescription>
</Product>
<Series id="TST903350550001" action="override" title="Seasons - S1">
<EpgDescription locale="fr_FR">
<EpgElement key="Title">Seasons - S1</EpgElement>
<EpgElement key="Synopsis">Smart</EpgElement>
<EpgElement key="ShortTitle">Seasons - S1</EpgElement>
</EpgDescription>
<EpgDescription>
<EpgElement key="Aspect">16:9</EpgElement>
<EpgElement key="PromoImage">TST_ANT_1192194.jpg</EpgElement>
</EpgDescription>
</Series>
<Episode action="override" duration="1080" id="TST937279650001" title="Épisode 9" number="9" episodeList="9" seriesRef="TST903350550001">
<EpgDescription locale="fr_FR">
<EpgElement key="Title">Épisode 9</EpgElement>
<EpgElement key="Synopsis">George</EpgElement>
</EpgDescription>
<EpgDescription>
<EpgElement key="Aspect">16:9</EpgElement>
<EpgElement key="PromoImage">TST_ANT_1192194.jpg</EpgElement>
</EpgDescription>
<Media id="TSTM937279650001" fileName="TSTM937279650001.ts" frameDuration="27000" fileSize="477380316"/>
</Episode>
<VodItem action="override" contentRef="TST937279650001" id="TSTV937279650001" nodeRefs="TSTFRA1001" previewDate="2016-01-05T16:27:00Z" productRefs="TSTP937279650001" title="Épisode 9" broadcasterId="TST">
<EpgDescription>
<EpgElement key="Studio">Replay</EpgElement>
</EpgDescription>
<EpgDescription locale="fr_FR">
<EpgElement key="Title">Épisode 9</EpgElement>
<EpgElement key="Synopsis">George</EpgElement>
</EpgDescription>
<Period start="2018-07-05T16:27:00Z" end="2018-08-04T21:59:00Z"/>
</VodItem>
</ScheduleProvider>

这将满足您的需要。您只需要在使用findnodes找到的元素上调用setAttributes

use strict;
use warnings 'all';
use XML::LibXML;
my $filename         = 'sample.xml';
my $out_filename     = "$filename.new";
my $media_id_from    = 'MEDIAID_TEST';
my $vod_item_id_from = 'VODITEM_ID_TEST';
my $doc = XML::LibXML->load_xml(location => $filename);
my ($media) = $doc->findnodes('/ScheduleProvider/Episode/Media');
$media->setAttribute(id => $media_id_from);
my ($vod_item) = $doc->findnodes('/ScheduleProvider/VodItem');
$vod_item->setAttribute(id => $vod_item_id_from);
$doc->toFile($out_filename);

属性节点可以通过在属性名称前面加上@作为XPath的最后一个元素来获得,因此更改

my $mediaId = join '', map { $_->{id}; } $dom->findnodes('/ScheduleProvider/Episode/Media');
my $vodItemId = join '', map { $_->{id}; } $dom->findnodes('/ScheduleProvider/VodItem');

foreach my $attribute ($dom->findnodes('/ScheduleProvider/Episode/Media/@id') {
$attribute->setValue($mediaIdFrom);
}
foreach my $attribute ($dom->findnodes('/ScheduleProvider/VoidItem/@id') {
$attribute->setValue($VodItemIdFrom);
}

这将在每个id属性节点上迭代,允许您使用setValue()方法更新属性。

然后,您应该能够在dom对象上使用toFile()方法来写出更新的版本,而无需重新打开输入文件文件

相关内容

  • 没有找到相关文章

最新更新