如何使用perl从xml文件中删除重复的节点

时间:2011-11-22 10:02:03

标签: perl

我正在从多个创建一个xml文件,我需要从输出xml中删除重复的节点。我有这样的脚本来生成新的xml文件

 #!/usr/bin/perl
 use warnings;
 use strict;
 use XML::LibXML;
 use Carp;
 use File::Find;
 use File::Spec::Functions qw( canonpath );
 use XML::LibXML::Reader;
 use Digest::MD5 'md5';

 if ( @ARGV == 0 ) {
     push @ARGV, "c:/main/sav ";
     warn "Using default path $ARGV[0]\n  Usage: $0  path ...\n";
 }

 open( my $allxml, '>', "combined.xml" )
     or die "can't open output xml file for writing: $!\n";
 print $allxml '<?xml version="1.0" encoding="UTF-8"?>',
  "\n<Datainfo xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n";
 my %extract_md5;
 find(
      sub {
          return unless ( /(_str\.xml)$/ and -f );
          extract_information();
          return;
      },
      @ARGV
     );

 print $allxml "</Datainfo>\n";

 sub extract_information {
     my $path = $_;
     if ( my $reader = XML::LibXML::Reader->new( location => $path )) {
         while ( $reader->nextElement( 'Data' )) {
             my $elem = $reader->readOuterXml();
             my $md5 = md5( $elem );
             print $allxml $reader->readOuterXml() unless ( $extract_md5{$md5}++ );
         }

     }
     return;
 }

但是从上面的脚本打印xml这样的文件

combined.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Datainfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <data>
        <test>22</test>
        <info>sensor value</info>
        <sensor>
            <sensor value="23" temp="25"/>
        </sensor>
    </data>
    <data>
        <test>23</test>
        <info>sensor value</info>
        <sensor>
            <sensor value="24" temp="27"/>
        </sensor>
    </data>
    <data>
        <test>22</test>
        <info>sensor value</info>
        <sensor>
            <sensor value="22" temp="26"/>
        </sensor>
    </data>
</Datainfo>

在上面的xml文件中,我有两次重复数据元素test(22)。我需要使用test作为搜索文件的元素,如果找到相同的测试编号,那么该节点内的信息我需要删除整个节点信息。我尝试使用md5,但它从allxml文件中删除了重复的节点,但现在我需要搜索一个特定元素并删除整个节点信息,如果发生重复。请帮我解决这个问题。
像这样的输出

combined.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Datainfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <data>
        <test>22</test>
        <info>sensor value</info>
        <sensor>
            <sensor value="23" temp="25"/>
        </sensor>
    </data>
    <data>
        <test>23</test>
        <info>sensor value</info>
        <sensor>
            <sensor value="24" temp="27"/>
        </sensor>
    </data>
</Datainfo>

2 个答案:

答案 0 :(得分:1)

我通常使用XML::Simple来做这样的事情。

XML::Simple将您的XML文件存储在散列/数组结构中。这将自动消除您找到的重复问题(具体取决于您的配置)。

答案 1 :(得分:0)

您必须通过专门检查<test>内容而不是整个节点的md5来进行重复检查。

E.g。而不是my $md5 = md5( $elem );并在散列中存储$md5键,您需要提取<test>标记的内容并存储它。

我不想提供更多详细信息,因为您似乎只是垃圾邮件以及PerlMonks请求帮助您完成工作并复制/粘贴有些复杂的代码,您不必费心去理解它是如何工作的

http://www.perlmonks.org/?node_id=939272