我在这里阅读了其他一些主题,但这不适合我的示例。 我有一个XML文件,我想在其中查找和替换特定值。
我的脚本正在处理预期的结果,但是这很丑陋,因为我没有使用模块中的所有资源。
我已经尝试过$node->setData($content);
和$dom->toFile($filename)
,但没有成功。
问题:
目的是从Media (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>
答案 0 :(得分:2)
这将做您想要的。您只需要在setAttributes
上找到的元素上调用findnodes
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);
答案 1 :(得分:1)
通过在属性名称前加上@作为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()
方法来写出更新的版本,而不必重新打开输入文件