首页 > 解决方案 > 连接来自多个 XML 文件的元素

问题描述

我需要打开并解析几个 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>

标签: xmlperlxml-libxml

解决方案


在您的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;

推荐阅读