连接多个XML文件中的元素

时间:2018-08-09 18:19:28

标签: xml perl xml-libxml

我需要打开并解析几个XML文件,将数据保留在内存中,然后对结果进行排序。

脚本未完成,因为我不知道如何将信息保留在散列或变量中,这就是为什么我需要您的帮助。

Perl代码

#!/usr/local/bin/perl

use strict;
use warnings 'all';

use POSIX;
use XML::LibXML;

print strftime('%Y-%m-%d %H:%M:%S', localtime), "\n";

my $DIR = "/totest/";

# Looking for XML files
opendir(DIR, $DIR);
my @SEARCH = grep(/^XML-[0-9]{8}_[0-9]{6}.FR.*.FORTESTING.xml$/, readdir(DIR));
closedir(DIR);

my ($product, $series, $voditem, $episode) = ("", "", "", "");

# If data file so
if ( scalar(@SEARCH) ) {

    foreach ( @SEARCH ) {

        my $filename = $DIR . $_;
        my $doc      = XML::LibXML->load_xml(location => $filename);

        $product = $doc->getDocumentElement->findnodes("/ScheduleProvider/Product")->[0]->toString, "\n";
        $series  = $doc->getDocumentElement->findnodes("/ScheduleProvider/Series"->[0]->toString, "\n";
        $episode = $doc->getDocumentElement->findnodes("/ScheduleProvider/Episode")->[0]->toString, "\n";
        $voditem = $doc->getDocumentElement->findnodes("/ScheduleProvider/VodItem")->[0]->toString, "\n";
    }

    print "$series\n";
}

所需的输出

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ScheduleProvider id="FRT">
    <Product action="override" type="single">
        <Price currency="EUR">0.00</Price>
        <EpgDescription locale="fr_FR">
            <EpgElement key="Title">NO TITLE</EpgElement>
        </EpgDescription>
    </Product>
    <Product action="override" type="single">
        <Price currency="EUR">0.00</Price>
        <EpgDescription locale="fr_FR">
            <EpgElement key="Title">NO TITLE</EpgElement>
        </EpgDescription>
    </Product>
    <Series id="TS30200026214" action="override">
            <EpgElement key="IsRecordable">0</EpgElement>
    </Series>
    <Series id="TS20200026214" action="override">
            <EpgElement key="IsRecordable">0</EpgElement>
    </Series>
    <Episode action="override" id="TS303687645464" seriesRef="TS30200026214">
        <Media id="TS300687645464"/>
    </Episode>
    <Episode action="override" id="TS203182282260" seriesRef="TS20200026214">
        <Media id="TS200182282260"/>
    </Episode>
    <VodItem action="override" contentRef="TS303687645464" id="TS304687645464">
        <Period year="2017"/>
    </VodItem>
    <VodItem action="override" contentRef="TS203182282260" id="TS204182282260">
        <Period year="2018"/>
    </VodItem>
</ScheduleProvider>

XML-20170504_060444.FR.FORTESTING.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ScheduleProvider id="FRT">
    <Product action="override" type="single">
        <Price currency="EUR">0.00</Price>
        <EpgDescription locale="fr_FR">
            <EpgElement key="Title">NO TITLE</EpgElement>
        </EpgDescription>
    </Product>
    <Series id="TS30200026214" action="override">
            <EpgElement key="IsRecordable">0</EpgElement>
    </Series>
    <Episode action="override" id="TS303687645464" seriesRef="TS30200026214">
        <Media id="TS300687645464"/>
    </Episode>
    <VodItem action="override" contentRef="TS303687645464" id="TS304687645464">
        <Period year="2017"/>
    </VodItem>
</ScheduleProvider>

XML-20170505_073915.FR.FORTESTING.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ScheduleProvider id="FRT">
    <Product action="override" type="single">
        <Price currency="EUR">0.00</Price>
        <EpgDescription locale="fr_FR">
            <EpgElement key="Title">NO TITLE</EpgElement>
        </EpgDescription>
    </Product>
    <Series id="TS20200026214" action="override">
            <EpgElement key="IsRecordable">0</EpgElement>
    </Series>
    <Episode action="override" id="TS203182282260" seriesRef="TS20200026214">
        <Media id="TS200182282260"/>
    </Episode>
    <VodItem action="override" contentRef="TS203182282260" id="TS204182282260">
        <Period year="2018"/>
    </VodItem>
</ScheduleProvider>

1 个答案:

答案 0 :(得分:0)

在您的if (scalar(@SEARCH))块中,将代码更改为如下所示。它创建一个新的XML文档,并从打开的XML文档中添加所需的节点。我还清理了XML方法中一些不必要的冗长内容。

use strict;
use warnings;
use XML::LibXML;

# create new xml doc 
my $new_doc = XML::LibXML::Document->new('1.0','utf-8');
my $new_root = $new_doc->createElement('ScheduleProvider');
$new_root->setAttribute('id','FRT');

# for example purposes, let's say the file paths are in the command line arguments
for my $fn (@ARGV) {
    die "file $fn not found" unless -e $fn;

    my $doc = XML::LibXML->load_xml(location => $fn);
    my $dom = $doc->getDocumentElement;

    # add the nodes to the new xml doc       
    for my $xpath (qw<//Product //Series //Episode //VodItem>) {
         $new_root->appendChild($_) for $dom->findnodes($xpath);
    }                 
 }

 $new_doc->setDocumentElement($new_root);

 print $new_doc->toString;