perl XML 转换解决方案

发布于 2024-10-10 06:44:42 字数 306 浏览 12 评论 0原文

我是 Perl 和 CPAN 模块的初学者,

我想转换 xml 文件,包括:

<Item><Link>http://example.com/</Link></Item>....

<Item><Link>http://mysite.com/</Link></Item>....

您有智能解决方案吗 带有CPAN模块

I'm a beginner for Perl and CPAN Modules

I wanna convert a xml file include:

<Item><Link>http://example.com/</Link></Item>....

To

<Item><Link>http://mysite.com/</Link></Item>....

Do you have smart solutions ? with CPAN Module

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

二智少女 2024-10-17 06:44:42
  • 参见XML::Twig - 用于处理巨大的perl模块树模式的 XML 文档。
  • XML::Simple - Easy API维护 XML(esp 配置文件),

例如

use strict;
use warnings; 
use XML::Simple;
use Data::Dumper;

my $xml = q~<?xml version='1.0'?>
<root>
  <Item>
  <Link>http://example.com/</Link>
  </Item>
  <Item>
   <Link>http://example1.com/</Link>
  </Item>
</root>~;

print $xml,$/;

my $data = XMLin($xml);

print Dumper( $data );

foreach my $test (@{$data->{Item}}){
   foreach my $key (keys %{$test}){
       $test->{$key} =~ s/example/mysite/;
   }
}
 print XMLout($data, RootName=>'root', NoAttr=>1,XMLDecl => 1);

输出:

<?xml version='1.0'?>
<root>
  <Item>
  <Link>http://example.com/</Link>
  </Item>
  <Item>
   <Link>http://example1.com/</Link>
  </Item>
</root>
$VAR1 = {
          'Item' => [
                    {
                      'Link' => 'http://example.com/'
                    },
                    {
                      'Link' => 'http://example1.com/'
                    }
                  ]
        };
<?xml version='1.0' standalone='yes'?>
<root>
  <Item>
    <Link>http://mysite.com/</Link>
  </Item>
  <Item>
    <Link>http://mysite1.com/</Link>
  </Item>
</root>
  • see XML::Twig - A perl module for processing huge XML documents in tree mode.
  • or XML::Simple - Easy API to maintain XML (esp config files)

like,

use strict;
use warnings; 
use XML::Simple;
use Data::Dumper;

my $xml = q~<?xml version='1.0'?>
<root>
  <Item>
  <Link>http://example.com/</Link>
  </Item>
  <Item>
   <Link>http://example1.com/</Link>
  </Item>
</root>~;

print $xml,$/;

my $data = XMLin($xml);

print Dumper( $data );

foreach my $test (@{$data->{Item}}){
   foreach my $key (keys %{$test}){
       $test->{$key} =~ s/example/mysite/;
   }
}
 print XMLout($data, RootName=>'root', NoAttr=>1,XMLDecl => 1);

output:

<?xml version='1.0'?>
<root>
  <Item>
  <Link>http://example.com/</Link>
  </Item>
  <Item>
   <Link>http://example1.com/</Link>
  </Item>
</root>
$VAR1 = {
          'Item' => [
                    {
                      'Link' => 'http://example.com/'
                    },
                    {
                      'Link' => 'http://example1.com/'
                    }
                  ]
        };
<?xml version='1.0' standalone='yes'?>
<root>
  <Item>
    <Link>http://mysite.com/</Link>
  </Item>
  <Item>
    <Link>http://mysite1.com/</Link>
  </Item>
</root>
﹎☆浅夏丿初晴 2024-10-17 06:44:42

下面是使用 XML::Twig 的简单解决方案。与 XML::Simple 选项相比,无论 Link 元素位于 XML 中的哪个位置,它都有效,并且它将尊重文件的原始格式。如果 XML 包含混合内容,它也将起作用。

如果您需要就地更改文件,可以使用 parsefile_inplace 而不是 parsefile,我怀疑 subs_text 中的正则表达式可能需要在现实生活中需要改进,但是这段代码应该是一个很好的起点。

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots => { Link => \&replace_link, }, # process Link
                twig_print_outside_roots => 1,             # output everything else
              )
          ->parsefile( 'my.xml');

sub replace_link
  { my( $t, $link)= @_;
    $link->subs_text( qr{^http://example\.com/$}, 'http://mysite.com');
    $t->flush;               # or $link->print, outputs the modified (or not) link
  }           

A simple solution using XML::Twig is below. Compared with the XML::Simple option it works no matter where the Link elements are in the XML, and it will respect the original formatting of the file. It will also work if the XML contains mixed-content.

If you need to change the file in place, you can use parsefile_inplace instead of parsefile, and I suspect the regular expression in subs_text may need to be improved in real life, but this code should be a good starting point.

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots => { Link => \&replace_link, }, # process Link
                twig_print_outside_roots => 1,             # output everything else
              )
          ->parsefile( 'my.xml');

sub replace_link
  { my( $t, $link)= @_;
    $link->subs_text( qr{^http://example\.com/$}, 'http://mysite.com');
    $t->flush;               # or $link->print, outputs the modified (or not) link
  }           
樱花落人离去 2024-10-17 06:44:42

如果您需要的只是更改特定值,那么您实际上不需要任何特殊的东西,您可以简单地使用正则表达式:
从命令行:

perl -pi -e 's@http://example.com/@http://mysite.com/@g' file.xml

编辑:添加完整代码版本:

my $file = '/tmp/test.xml';

open IN, "<$file" or die "can't open $file $!";
open OUT, ">$file.tmp" or die "can't open $file.tmp $!";
foreach (<IN>) {
    s@http://example.com/@http://mysite.com/@g;
    print OUT $_;
}
close(IN);
close(OUT);

rename("$file.tmp", "$file")

If all you need is changing a specific value, you don't really need anything special, you can simply use regexp:
from command line :

perl -pi -e 's@http://example.com/@http://mysite.com/@g' file.xml

edit : adding full code version :

my $file = '/tmp/test.xml';

open IN, "<$file" or die "can't open $file $!";
open OUT, ">$file.tmp" or die "can't open $file.tmp $!";
foreach (<IN>) {
    s@http://example.com/@http://mysite.com/@g;
    print OUT $_;
}
close(IN);
close(OUT);

rename("$file.tmp", "$file")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文