0

非常に長い xml があり、非常に深くネストされたタグの 1 つの属性値を更新したいので、ノードごとに移動したくありません。また、以下に示すように、目的のノードの構造は常に同じではありません。 入力 XML は次のとおりです。

<Re>
<Co Class="Parameter" ID="CSCP001" Status="Available">
<FileSpec URL="c://mine/testfiles/wln/c.txt"/>
<CoOp Operation="Tag" SourceCS="RGB" SourceObjects="All">
<FileSpec Resource="SourceProfile" URL="c://mine/testfiles/wln/d.txt"/>
</CoOp>
</Co>
<Ru Class="Parameter" ID="IDR002" PartIDKeys="Run" Status="Available">
<Ru EndOfDocument="true" Pages="0" Run="1" RunTag="First">
<La>
<FileSpec URL="c://mine/testfiles/wln/e.txt"/>
</La>
</Ru>
</Ru>
</Re>

xmlを次のように出力したい

<Re>
<Co Class="Parameter" ID="CSCP001" Status="Available">
<FileSpec URL="d://yours/wln/c.txt"/>
<CoOp Operation="Tag" SourceCS="RGB" SourceObjects="All">
<FileSpec Resource="SourceProfile" URL="d://yours/wln/d.txt"/>
</CoOp>
</Co>
<Ru Class="Parameter" ID="IDR002" PartIDKeys="Run" Status="Available">
<Ru EndOfDocument="true" Pages="0" Run="1" RunTag="First">
<La>
<FileSpec URL="d://yours/wln/e.txt"/>
</La>
</Ru>
</Ru>
</Re>

xml simple、xmllib を使用してみましたが、必要なことができませんでした。私はperlプログラミングが初めてです。

use XML::LibXML qw( );
use XML::LibXML;
use Data::Dumper;  

my $xml = "a.txt";
my $xpath_expression = 'FileSpec';

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($xml) or warn "Could not";

my $parser1 = XML::LibXML::Element->new($xml);


for my $FileSpec1 ($doc->getElementsByTagName('FileSpec')) 
{
print $FileSpec1;
my $xpath = '$FileSpec1/@URL';
my ($attr) = $doc->findnodes($xpath);    
$attr->setValue('dfdsa'); 
my ($URL1) = $FileSpec1->findvalue('@URL');
print $URL1;
}

$node->setAttribute( $aname, $avalue ); を使用してみました。しかし、これは例外をスローしています。ご意見をお聞かせください。

4

2 に答える 2

4

コードが複雑すぎます。パーサーも要素も必要ありません。URL を見つけて変更するだけです。

#!/usr/bin/perl
use warnings;
use strict;

use XML::LibXML;

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

for my $url ($xml->findnodes('//FileSpec/@URL')) {
    my $value = $url->getValue;
    $value =~ s{c://mine/testfiles}{d://yours};
    $url->setValue($value);
}

$xml->toFile('new.xml');
于 2013-09-17T07:43:48.197 に答える
1

モジュールで試すことができXML::Twigます。twig_handlers必要なタグを選択してハンドラーをトリガーするオプションがあります。デフォルト変数$_には要素があり、そのメソッドを使用すると、set_att()その値を簡単に変更できます。

#!/usr/bin/env perl

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

my $new_url = q{d://yours/wln/d.txt};

my $twig = XML::Twig->new(
        twig_handlers => {
                'FileSpec' => sub { $_->set_att( 'URL', $new_url ) }
         },
        pretty_print => 'indented',
)->parsefile( shift )->print();

次のように実行します。

perl script.pl xmlfile

これにより、次の結果が得られます。

<Re>
  <Co Class="Parameter" ID="CSCP001" Status="Available">
    <FileSpec URL="d://yours/wln/d.txt"/>
    <CoOp Operation="Tag" SourceCS="RGB" SourceObjects="All">
      <FileSpec Resource="SourceProfile" URL="d://yours/wln/d.txt"/>
    </CoOp>
  </Co>
  <Ru Class="Parameter" ID="IDR002" PartIDKeys="Run" Status="Available">
    <Ru EndOfDocument="true" Pages="0" Run="1" RunTag="First">
      <La>
        <FileSpec URL="d://yours/wln/d.txt"/>
      </La>
    </Ru>
  </Ru>
</Re>

EDITMirodのバージョンは、以下を使用したより効率的な解析のコメントで指摘されていますtwig_roots()

#!/usr/bin/env perl

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

my $new_url = q{d://yours/wln/d.txt};

my $twig = XML::Twig->new(
        twig_roots => {
                'FileSpec' => sub { $_->set_att( 'URL', $new_url ); $_->flush }
        },
        twig_print_outside_roots => 1,
        pretty_print => 'indented',
)->parsefile( shift );
于 2013-09-17T07:12:06.820 に答える