フィルタテキストXMLファイル

フィルタテキストXMLファイル

特定のフィールドのみをフィルタリングしたい大規模な(数十万のレコードを含む)XMLファイルがあります。ファイル構成の例:

<A>
<id>123</id>
<B>
   <C>value1</C>
   <D>value2</D>
   ....
   <E></E>
</B>
<Z></Z>
...
<Y></Y>
<A>

このXMLファイルをフィルタリングし、CフィールドとDフィールドに含まれるIDとデータのみを含めたいです。

どうすればいいですか?

答え1

これxmlstarletこのツールは次のことを行います。

xmlstarlet sel -t -m /A -o ID, -v id -n -o C, -v //C -n -o D, -v //D -n test.xml 

ルート要素()-m /Aの下の各Aについて、文字列「ID」(-o ID,)、idの内容()-v id、改行()を印刷し、子要素C()、D()、-nおよびその項目についても同様です。ヘッダー。二重スラッシュは、「ノードの下のどこにでも一致」を意味するXPathです。-v //C-v //D

テストファイルを使用して自分のシステムでテストした結果は、カンマ区切りの出力です。

ID,123
C,value1
D,value2

ヘッダーが必要ない場合は、-o <whatever>パラメータを省略してください。

ありがとうこの記事説明する。

答え2

この質問に正しく答えるには、理想的にはより良い例が必要です。効果的なxmlは良いスタートです。

また - 希望の出力の例です。たとえば、生成されたXMLで<C>要素<D>が終わる場所を指定する必要はありません。彼らすでに子項目 - ルートだけでなく親項目も維持するか、親に戻しますか<B>BCD

しかし、一般的に言えば、使用と再構築は非常に簡単ですXMLXML::Twigperl

たとえば、次のようになります。

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my @wanted = qw ( C D id );


my %wanted = map { $_ => 1 } @wanted; 

sub delete_unwanted_tags {
   my ( $twig, $element ) = @_;
   my $tag = $element -> tag;
   if ( not $wanted{$tag} ) {
        $element -> delete;
   }
}

my $twig = XML::Twig -> new ( twig_handlers => { _all_ => \&delete_unwanted_tags } );
$twig -> parse ( \*DATA );
$twig -> print;

__DATA__
<A>
<id>123</id>
<B>
   <C>value1</C>
   <D>value2</D>
   <E></E>
</B>
<Z></Z>
<Y></Y>
</A>

「維持」とは言わなかったので、<B>結果は次のようになります。

<A>
  <id>123</id>
</A>

<B>リストに追加wanted

<A>
  <id>123</id>
  <B>
    <C>value1</C>
    <D>value2</D>
  </B>
</A>

ただし、目的の操作が親を再割り当てし、CDのように入力した場合A

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

my @wanted   = qw ( id);
my @reparent = qw ( C D );

#turn the above into hashes, so we can do "if $wanted{$tag}"
my %wanted   = map { $_ => 1 } @wanted;
my %reparent = map { $_ => 1 } @reparent;

sub delete_unwanted_tags {
    my ( $twig, $element ) = @_;
    my $tag = $element->tag;
    if ( not $wanted{$tag} ) {
        $element->delete;
    }
    if ( $reparent{$tag} ) {
        $element->move( 'last_child', $twig->root );
    }
}

my $twig = XML::Twig->new(
    pretty_print  => 'indented_a',
    twig_handlers => { _all_ => \&delete_unwanted_tags }
);
$twig->parse( \*DATA );
$twig->print;

__DATA__
<A>
<id>123</id>
<B>
   <C>value1</C>
   <D>value2</D>
   <E></E>
</B>
<Z></Z>
<Y></Y>
</A>

注 - 「木の枝ハンドラ」終わり各要素の値(閉じるタグが見つかったとき)が機能する理由です。処理(および削除)を完了する前に、再帰的に合計を見つけますCDB

これで以下が生成されます。

<A>
  <id>123</id>
  <C>value1</C>
  <D>value2</D>
</A>

__DATA__上記では、XMLとスキルを説明できるものを\*DATA使用しました。parseおそらくparsefile('my_file.xml')使用する必要がありますparse(\*DATA)

答え3

ltXML2ツールキット(エジンバラ大学)のlxgrepを使用してください。

$ lxgrep -w A '(id|C|D)' test.xml
<A>
<id>123</id>
<C>value1</C>
<D>value2</D>
</A>

このタイプのツールの使用は遠く直接するよりも速くて安定しています。


XML FAQ:http://xml.silmaril.ie/

関連情報