1

私は今日、仕事でこれに苦労しました。以下のような XML ファイルを読み込もうとしています (すぐに入力したものです)。show_idコードの CSV ファイルがあります。だから私はそれらを読み込んでハッシュに入れました。次に、.xml を使用して XML ファイルを読み込みますXML::Simple

次に、以下の要素のコードを比較しshow_id(オンラインの例のように配列を使用してループを実行し、それ$a = $data->{Element1}->{Element2}->{show_id}が見つかった)、ハッシュ テーブルに一致するかどうかを確認します。ビンゴ。問題なく動作するようになりました。

Element2では、中間の 2 つの要素を とshow_idの値に一致させるABC11としますABC12。ここで、一致するファイルの新しいファイルを作成する必要があります。それでやってみXMLoutましたが、読み込んだタグ構造全体が失われているようです。

以下のデータを読み込んでレコードABC10ABC14削除し、たとえば同じ形式でファイルを絞り出す方法はありますか? それが理にかなっているかどうか教えてください。

また、私は職場でのみXML::SimpleインストールXML::Parserしています。助けてください!!!

<?xml version="1.0" encoding="ISO-8859-1"?>
<main>
  <Element1>
    <Element2>
        <show/>
        <show_id>ABC10</show_id>
        <staring>
            <show_header>This is a test</show_header>
        </staring>
    </Element2>
        <Element2>
            <show/>
            <show_id>ABC11</show_id>
            <staring>
                <show_header>This is a test</show_header>
            </staring>
    </Element2>
        <Element2>
            <show/>
            <show_id>ABC12</show_id>
            <staring>
                <show_header>This is a test</show_header>
            </staring>
    </Element2>
        <Element2>
            <show/>
            <show_id>ABC14</show_id>
            <staring>
                <show_header>This is a test</show_header>
            </staring>
    </Element2>
  </Element1>
</main>
4

3 に答える 3

2

インストールできる場合 XML::Twig 、これはあなたが好むかもしれない解決策です。

use strict;
use warnings;

use XML::Twig;

my %keep = (
  ABC11 => 1,
  ABC12 => 1,
);

my $twig = XML::Twig->new(
  keep_spaces => 1,
  twig_handlers => { Element2 => \&Element2 }
);  

$twig->parsefile('data.xml');
$twig->print;

sub Element2 {
  my ($twig, $elem) = @_;
  my $show_id = $elem->first_child_text('show_id');
  $elem->delete unless $keep{$show_id};
}

または、必要に応じて XML::LibXML 、これが機能します

use strict;
use warnings;

use XML::LibXML;

my %keep = (
  ABC11 => 1,
  ABC12 => 1,
);

my $xml = XML::LibXML->load_xml(location => 'data.xml');

for my $elem2 ($xml->findnodes('//Element2')) {
  my $show_id = $elem2->find('show_id');
  $elem2->parentNode->removeChild($elem2) unless $keep{$show_id};
}

print $xml->toString;

これらのプログラムの出力は同じです。

出力

<?xml version="1.0" encoding="ISO-8859-1"?>
<main>
  <Element1>

        <Element2>
            <show/>
            <show_id>ABC11</show_id>
            <staring>
                <show_header>This is a test</show_header>
            </staring>
    </Element2>
        <Element2>
            <show/>
            <show_id>ABC12</show_id>
            <staring>
                <show_header>This is a test</show_header>
            </staring>
    </Element2>

  </Element1>
</main>
于 2012-12-06T23:50:13.847 に答える
1

まず、使用されていない要素を取り除きます。

$data->{Element1}{Element2} = [
  grep { $_->{show_id} =~ /^ABC1[12]$/ } @{$data->{Element1}{Element2}}
];

そして、XML 形式で書き出します。( ではNoAttr => 1、ハッシュは属性ではなくネストされた要素として表されます。)

print XMLout($data, NoAttr => 1, RootName => "main");

KeepRoot => 1XMLin および XMLout に渡して、 の代わりにルート要素 (「main」) を処理できRootName => 1ます。その場合は、 を使用してください$data->{main}{Element1}{Element2}

于 2012-12-06T21:30:58.427 に答える
1

入ってくるものと同じものを出していきたい場合は、XML::Simple を使用しないでください。XML::Rulesを使用したソリューションは次のとおりです。

use strict;
use warnings;

use XML::Rules;

my @keep_these = qw(
  ABC11
  ABC12
);
my %keep; $keep{$_}++ for @keep_these;

my @rules = (
  Element2 => sub {
    my $id = $_[1]->{show_id}{_content};
    return unless $keep{$id};
    return $_[0] => $_[1];
  },
);
my $p = XML::Rules->new(
  style => 'filter',
  rules => \@rules,
  stripspaces => 3,
);

$p->filter(\*DATA, \*STDOUT);

__END__
<?xml version="1.0" encoding="ISO-8859-1"?>
<main>
  <Element1>
    <Element2>
etc.
于 2012-12-06T21:31:29.463 に答える