排序&将XML文档与Perl / XML :: Twig合并

时间:2011-12-21 13:34:40

标签: xml perl xml-twig

我在目录中有许多XML文件需要排序并合并到一个文件中。文件格式如下:

File1.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypea>

File2.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>112</docnumber>
  </header>
</doctypea>

File3.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypeb>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypeb>

File4.xml:

<?xml version="1.0" encoding="utf-8"?>
<doctypeb>
  <header someattr="1">
    <docnumber>112</docnumber>
  </header>
</doctypeb>

此目录中的所有文件都需要按以下标准排序:

  1. documentnumber
  2. doctype(a或b)
  3. 然后需要合并它们,因此输出文件应如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <doctypea>
      <header someattr="1">
        <docnumber>111</docnumber>
      </header>
    </doctypea>
    <doctypeb>
      <header someattr="1">
        <docnumber>111</docnumber>
      </header>
    </doctypeb>
    <doctypea>
      <header someattr="1">
        <docnumber>112</docnumber>
      </header>
    </doctypea>
    <doctypeb>
      <header someattr="1">
        <docnumber>112</docnumber>
      </header>
    </doctypeb>
    

    为了实现这一点,我尝试使用XML:Perl中的Twig。到目前为止,我有以下代码:

    use XML::Twig;
    
    my $xmldir = "/xmlfiles";
    my $parser = XML::Twig->new(pretty_print => 'indented');
    
    opendir(DIR, "$xmldir");
    my @FILES= readdir(DIR);
    closedir(DIR);
    
    foreach (@FILES) {
            if ($_ ne "." && $_ ne "..") {
                    print "reading file: $xmldir/$_\n";
                    $parser->parsefile("$xmldir/$_");
            }
    }
    

    此时我似乎无法找出正确的语法来从解析器中获取我想要的元素。

    1。如何获取根元素的值(&#34; doctypea&#34;或&#34; doctypeb&#34;)?

    2。我假设我需要(1)才能将语法编码下载到docnumber字段?

    我的计划是使用doctype%number构建某种类型以进行排序,我不确定将它们与之合并的最简单方法。

    感谢任何建议!

2 个答案:

答案 0 :(得分:5)

请在下面找到应该让您入门的小例子。它显示了如何从XML文件中获取与您类似的数据(我修复了标记以匹配并引用someattr值以获取有效的XML)。您可以使用类似的方法收集所需的数据并生成输出。

use XML::Twig;

XML::Twig->new(twig_handlers => {
    '/*'        => sub { print $_->gi;           },     # doctypea
    'docnumber' => sub { print $_->trimmed_text; },     # 111
})->parse(\*DATA);    # use parsefile('xxx.xml') to parse a file

__DATA__
<?xml version="1.0" encoding="utf-8"?>
<doctypea>
  <header someattr="1">
    <docnumber>111</docnumber>
  </header>
</doctypea>

答案 1 :(得分:1)

正如daxim所注意到的,您的文件不是有效的XML,但您可以使用正则表达式处理它们。如果文件不是太大,您可以将文件粘贴到您根据其内容排序的单个字符串中。

use File::Slurp qw( read_dir ) ;
my $xmldir=".";
my %files = map {
        s/^.*$//m; 
        /<doctype([ab])>/; my $x=ord($1) - ord('a');
        /<docnumber>(\d+)</docnumber>/; $x += 10*$2;
        $x => $_
    } read_dir($xmldir);
print join("", map { $files{$_} } sort keys %files);

我没有调试此代码。 print join("", values %files);也可能有用。