使用Perl编写xml文件

时间:2015-10-01 07:31:33

标签: xml perl

我是xml的新手。我有10个XML文件,其中包含一些“挤压报告”,如下所示(我不是在寻找答案,只是指导我如何处理它):

<SquishReport>
<test name="mat_tst_versions">
<prolog time="2015-06-16T13:49:54+02:00"/>
<message type="FATAL" time="2015-06-16T13:50:54+02:00">
    <description><![CDATA[Execution error]]></description>
    <description type="DETAILED"><![CDATA[squishrunner exited with code 3 when executing tst_start_app]]></description>
</message>
<test name="tst_check_versions">
    <prolog time="2015-06-16T13:50:55+02:00"/>
    <message line="274" type="LOG" file="C:\test\scripts\utilities.py" time="2015-06-16T13:50:59+02:00">
        <description><![CDATA[is 64 bit windows version: True]]></description>
    </message>            
    <message line="124" type="LOG" file="C:\test\mat_tst\tst_check_versions\test.py" time="2015-06-16T13:50:59+02:00">
        <description><![CDATA[    path exists!]]></description>
    </message>
    <message line="129" type="FAIL" file="C:\test\mat_tst\tst_check_versions\test.py" time="2015-06-16T13:50:59+02:00">
        <description><![CDATA[expected version: 1.0.0.107]]></description>
    </message>
    <verification line="132" type="" name="" file="C:\test\mat_tst\tst_check_versions\test.py">
        <result type="PASS" time="2015-06-16T13:50:59+02:00">
            <description>version check test case passes!</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <epilog time="2015-06-16T13:50:59+02:00"/>
</test>        
<test name="tst_scheduler_1">
    <prolog time="2015-06-16T13:51:00+02:00"/>
    <message line="62" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:51:00+02:00">
        <description><![CDATA[count = 0]]></description>
    </message>
    <message line="125" type="LOG" file="C:\test\scripts\start_stop.py" time="2015-06-16T13:51:06+02:00">
        <description><![CDATA[duration of start of C: 5132ms]]></description>
    </message>
    <message line="172" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:51:19+02:00">
        <description><![CDATA[application name = C]]></description>
    </message>
    <message line="184" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:51:19+02:00">
        <description><![CDATA[start application: C]]></description>
    </message>
    <message line="213" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:51:19+02:00">
        <description><![CDATA[Scheduler Label exists]]></description>
    </message>
    <message line="219" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:51:19+02:00">
        <description><![CDATA[Scheduler Counter exists]]></description>
    </message>
    <verification line="368" type="" name="" file="C:\test\mat_tst\tst_scheduler_1\test.py">
        <result type="FAIL" time="2015-06-16T13:52:01+02:00">
            <description>different types elements</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <verification line="369" type="" name="" file="C:\test\mat_tst\tst_scheduler_1\test.py">
        <result type="FAIL" time="2015-06-16T13:52:01+02:00">
            <description>name_list= ['Scheduler', 'NCU', 'PLCSimAdv', 'simNCK', 'MCP']</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <verification line="370" type="" name="" file="C:\test\mat_tst\tst_scheduler_1\test.py">
        <result type="FAIL" time="2015-06-16T13:52:01+02:00">
            <description>typ_list= ['Scheduler', u'NCU', u'PLCSimAdv']</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <message line="393" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:52:08+02:00">
        <description><![CDATA[:840evoVC.lblClockCounter_Edit = 0]]></description>
    </message>
    <verification line="411" type="" name="" file="C:\test\mat_tst\tst_scheduler_1\test.py">
        <result type="FAIL" time="2015-06-16T13:52:08+02:00">
            <description>scheduler counter 1. read, n=0: Scheduler= 0</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <verification line="414" type="" name="" file="C:\test\mat_tst\tst_scheduler_1\test.py">
        <result type="FAIL" time="2015-06-16T13:52:08+02:00">
            <description>scheduler counter 2. read, n=0: Scheduler= 0</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <message line="421" type="LOG" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:52:08+02:00">
        <description><![CDATA[scheduler counter 1. read < counter 2. read, n=0: Scheduler= 0]]></description>
    </message>
    <message line="484" type="ERROR" file="C:\test\mat_tst\tst_scheduler_1\test.py" time="2015-06-16T13:52:29+02:00">
        <description><![CDATA[Script Error]]></description>
        <description type="DETAILED"><![CDATA[LookupError: Object ':840evoVC.chkSchedule_CheckBox_2' not ready.]]></description>
    </message>
    <epilog time="2015-06-16T13:52:29+02:00"/>
</test>
<test name="tst_run_plc">
    <prolog time="2015-06-16T13:52:30+02:00"/>
    <verification line="45" type="" name="" file="C:\test\mat_tst\tst_run_plc\test.py">
        <result type="FAIL" time="2015-06-16T13:52:30+02:00">
            <description>user path folder already exists!</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <message line="125" type="LOG" file="C:\test\scripts\start_stop.py" time="2015-06-16T13:52:34+02:00">
        <description><![CDATA[duration of start of 840evoVC: 4263ms]]></description>
    </message>
    <message line="54" type="LOG" file="C:\test\mat_tst_840evovc\tst_run_plc\test.py" time="2015-06-16T13:52:34+02:00">
        <description><![CDATA[start ok, duration = 4263000]]></description>
    </message>
    <message line="64" type="LOG" file="C:\test\mat_tst_840evovc\tst_run_plc\test.py" time="2015-06-16T13:52:34+02:00">
        <description><![CDATA[application started: 840evoVC]]></description>
    </message>
    <message line="78" type="LOG" file="C:\test\mat_tst_840evovc\tst_run_plc\test.py" time="2015-06-16T13:52:39+02:00">
        <description><![CDATA[PLC Sim Advanced tmp user files are the expected files]]></description>
    </message>
    <message line="263" type="LOG" file="C:\test\scripts\start_stop.py" time="2015-06-16T13:52:45+02:00">
        <description><![CDATA[all applications are closed]]></description>
    </message>
    <message line="87" type="LOG" file="C:\test\mat_tst_840evovc\tst_run_plc\test.py" time="2015-06-16T13:52:45+02:00">
        <description><![CDATA[close application ok]]></description>
    </message>
    <epilog time="2015-06-16T13:52:45+02:00"/>
</test>
<test name="tst_app_resources">
    <prolog time="2015-06-16T13:52:47+02:00"/>
    <message line="65" type="LOG" file="C:\test\mat_tst\tst_app_resources\test.py" time="2015-06-16T13:52:49+02:00">
        <description><![CDATA[count:0]]></description>
    </message>
    <message line="125" type="LOG" file="C:\test\scripts\start_stop.py" time="2015-06-16T13:52:53+02:00">
        <description><![CDATA[duration of start: 4176ms]]></description>
    </message>
    <message line="73" type="LOG" file="C:\test\mat_tst\tst_app_resources\test.py" time="2015-06-16T13:52:53+02:00">
        <description><![CDATA[start ok, duration = 4176000]]></description>
    </message>
    <message line="43" type="LOG" file="C:\test\scripts\win32utilities.py" time="2015-06-16T13:53:00+02:00">
        <description><![CDATA[Application 840evovc only exists once]]></description>
    </message>            
    <message line="138" type="ERROR" file="C:\test\mat_tst_\tst_app_resources\test.py" time="2015-06-16T13:53:30+02:00">
        <description><![CDATA[Script Error]]></description>
        <description type="DETAILED"><![CDATA[LookupError: Object ':chkSchedule_CheckBox_2' not ready.
            Called from:
        C:\test\mat_tst\tst_app_resources\test.py: 82]]></description>
    </message>
    <epilog time="2015-06-16T13:53:30+02:00"/>
</test>
<test name="tst_reset">
    <prolog time="2015-06-16T13:53:32+02:00"/>   
    <message line="260" type="LOG" file="C:\test\scripts\start_stop.py" time="2015-06-16T13:56:12+02:00">
        <description><![CDATA[Process exited.]]></description>          
    </message>
    <message line="263" type="LOG" file="C:\test\scripts\start_stop.py" time="2015-06-16T13:56:12+02:00">
        <description><![CDATA[all applications are closed]]></description>
    </message>
    <message line="284" type="LOG" file="C:\test\mat_tst\tst_reset\test.py" time="2015-06-16T13:56:12+02:00">
        <description><![CDATA[application closed]]></description>
    </message>
    <verification line="287" type="" name="" file="C:\test\mat_tst\tst_reset\test.py">
        <result type="PASS" time="2015-06-16T13:56:12+02:00">
            <description>tst_reset_1 ok</description>
            <description type="DETAILED"></description>
        </result>
    </verification>
    <epilog time="2015-06-16T13:56:12+02:00"/>
</test>
<epilog time="2015-06-16T13:56:13+02:00"/>
</test> 
</SquishReport>

现在我想创建另一个XML文件,其中包含XML文件的摘要。我需要在新的XML文件中只需要每个文件的</test> </SquishReport>然后一行链接

<result state= "Passed" href="link to the file"*.xml />
如果"Passed" <result type="PASS",则

"NOT Passed"

总的来说,我对新XML文件的期望是:

<?xml version="1.0" encoding="utf-8"?>
<summary>
  <testcase name="name of testcase1">
     <result state= "Passed" href="link to file1"*.xml /> (for the first file)
     <result state= "Passed" href="link to file2"*.xml /> (for the second file)
     ......
  <testcase/>
  <testcase name="name of testcase2">
     <result state= "Passed" href="link to file1"*.xml /> (for the first file)
     <result state= "Passed" href="link to file2"*.xml /> (for the second file)
     ......
  <testcase/>
  ....
  <testcase name="name of testcasen">
     <result state= "Passed" href="link to file1"*.xml /> (for the first file)
     <result state= "Passed" href="link to file2"*.xml /> (for the second file)
     ......
  <testcase/>
<summary/>

编辑:这是我到目前为止所拥有的:

  sub FileCount
{
chdir( $dir ) or die "Couldn't go inside $dir directory, $!";
opendir(my $dh, $dir) or die "$0: $dir: $!\n";
while (my $file = readdir($dh)) {
    # We only want files
     next unless (-f "$dir/$file");
    # Use a regular expression to find files ending in .xml
     next unless ($file =~ m/$suff$/);

     my $xml = XML::LibXML->load_xml(location => $file);

    # Iterate the entries                           
     for my $test ($xml->findnodes('/SquishReport/test/test')) {
        my $name_test = $test->findvalue('@name');  

        # looks for if the results is OK or not
        for my $result ($test->findnodes('./verification/result')) {
            my $type_result = $result->findvalue('@type');
            ### -----------------------------------------------------------------------
             my $doc = XML::LibXML::Document->new('1.0', 'utf-8');
             my $root = $doc->createElement("summary");
             $root->setAttribute('testcase_name'=> "$name_test");

             for my $case_name (keys %tags) {
                 my $tag = $doc->createElement($case_name);
                 my $value = $tags{$case_name};
                 $tag->appendTextNode($value);
                 $root->appendChild($tag);
             }

            $doc->setDocumentElement($root);
            ### -----------------------------------------------------------------------
            print "$type_result = $value_result \n";
            if (($type_result eq "WARNING") || ($type_result eq "FAIL") || ($type_result eq "ERROR") || ($type_result eq "FATAL")){
                $value_result = "OK";
                print "***********  $name_test is not OK *********** \n\n "; 
            }
            else{
                $value_result = "NOT_OK";
                print "***********  $name_test is OK *********** \n\n ";
            }
        }
        print "\n";
     }
    #}
     print "$file\n";       
     $count = $count + 1;
}
closedir($dh);  

my $filename = 'report.xml';
open(my $fh, '>', $filename) or die "Could not open file '$filename' $!";
print $fh $doc->toString();
close $fh;

2 个答案:

答案 0 :(得分:2)

我会这样做:

  • 使用XML::Twig(因为我喜欢它)。
  • 创建一个&#34;父母&#34; XML文档
  • 迭代每个XML文件,并使用cut中的pasteXML::Twig方法传输内容(并在必要时修剪)。我非常确定XML::LibXML也可以这样做,如果您愿意的话。
  • 打印&#34;父母&#34;文档。

有点像这样:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $new_xml = XML::Twig->new( pretty_print => 'indented_a' );
$new_xml->set_root( XML::Twig::Elt->new('summary') );
$new_xml->set_xml_version('1.0');
$new_xml->set_encoding('utf-8');

my $input_processor = XML::Twig->new->parsefile('sample_squish.xml');
foreach my $result ( $input_processor->findnodes('//result') ) {
    $result->cut;
    $result->paste( $new_xml->root );
}

open( my $output, '>', 'summary.xml' ) or die $!;
print {$output} $new_xml->sprint;
close($output);

您需要:

  • 使用foreach / glob
  • 重复您的文件(我只有一个样本)
  • 选择findnodes表达式。以上只收集result个元素,但我认为你想要更多。请记住 - 您可以再次findnodes,或使用children作用于...子节点,或parent作用于父节点。 (例如$result -> parent -> att('file')
  • 修改元素。
  • 将它们粘贴到原始文档中。

我无法弄清楚您的测试用例/名称如何从源映射到摘要 - 因此,如果您愿意,知道可以添加 new 节点也可能有用:< / p>

my $testcase = $new_xml -> root -> insert_new_elt('testcase', { name => "name_of_the_test" }); 
$testcase ->set_att('some_other_att', 42);
$result->cut;
$result->paste( $testcase );

这会将$result元素从一个文件插入到新文档中新创建的testcase元素中。

答案 1 :(得分:0)

您正在为每个测试创建一个文件。您需要将文档创建(以及根创建等)提升出循环。

XPATH / SquishReport / test / test看起来好像应该是/ SquishReport / test

而且,在某些时候你需要用$ doc做一些事情(比如写一个文件)