想要根据标签拆分 UNIX xml 文件

Want to split an UNIX xml file based on tags

我有一个 XML 文件,其中包含如下批次。

我想使用 shell 脚本根据标签将此文件拆分为 5 个文件。 请帮助,提前致谢。

<Items>
<Item>
<Title>Title 1</Title>
<DueDate>01-02-2008</DueDate>
</Item>
<Item>
<Title>Title 2</Title>
<DueDate>01-02-2009</DueDate>
</Item>
<Item>
<Title>Title 3</Title>
<DueDate>01-02-2010</DueDate>
</Item>
<Item>
<Title>Title 4</Title>
<DueDate>01-02-2011</DueDate>
</Item>
<Item>
<Title>Title 5</Title>
<DueDate>01-02-2012</DueDate>
</Item>
</Items>

期望的输出:

<Items>
<Item>
<Title>Title 1</Title>
<DueDate>01-02-2008</DueDate>
</Item>
</Items>

我建议 - 安装 XML::Twig which includes the rather handy xml_split 实用程序。那可能会做你需要的。例如:

xml_split -c Item

不过,我想说的是您要完成的事情并不容易,因为您要拆分并保留 XML 结构。您无法使用基于 line/regex 的标准工具来完成。

但是您可以使用解析器:

#!/usr/bin/env perl

use strict;
use warnings;
use XML::Twig;

my @item_list;

sub cut_item {
    my ( $twig, $item ) = @_;
    my $thing = $item->cut;
    push( @item_list, $thing );

}

my $twig = XML::Twig->new(
    twig_handlers => { 'Item' => \&cut_item }
);
$twig->parse(<>);

my $itemcount = 1;

foreach my $element (@item_list) {
    my $newdoc = XML::Twig->new( 'pretty_print' => 'indented_a' );
    $newdoc->set_root( XML::Twig::Elt->new('Items') );

    $element->paste( $newdoc->root );
    $newdoc->print;
    open( my $output, ">", "items_" . $itemcount++ . ".xml" );
    print {$output} $newdoc->sprint;
    close($output);
}

这使用 XML::Twig 库从您的 XML 中提取每个 Item 元素(在 STDIN 上传输,或通过 myscript.pl yourfilename)。

然后迭代所有它找到的,添加一个 Items header,并将其打印到一个单独的文件中。如果你有一个更复杂的根,这种方法可能会更麻烦一点,但如果你这样做的话,它是可以适应的。