1

ディレクトリに多くのXMLファイルがあり、並べ替えて1つのファイルにマージする必要があります。ファイルの形式は次のとおりです。

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. 書類番号
  2. doctype(aまたはb)

次に、それらをマージする必要があるため、出力ファイルは次のようになります。

<?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>

これを実現するために、PerlでXML: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.ルート要素("doctypea"または"doctypeb")の値を取得するにはどうすればよいですか?

2. docnumberフィールドまでノードを解析するために(1)それが必要だと思いますか?

私の計画は、ソートするためにdoctype%numberを使用してある種のhasを構築することですが、それらをそれとマージする最も簡単な方法はわかりません。

アドバイスに感謝します!

4

2 に答える 2

5

始めるための小さな例を以下に示します。someattrこれは、あなたと同様のXMLファイルからデータを取得する方法を示しています(有効な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>
于 2011-12-21T15:22:03.677 に答える
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);動作する可能性があります。

于 2011-12-21T15:37:45.870 に答える