【问题标题】:In Perl, how can I change an element in an XML file without changing the format of the XML file?在 Perl 中,如何在不更改 XML 文件格式的情况下更改 XML 文件中的元素?
【发布时间】:2010-11-22 14:23:00
【问题描述】:

我有一个格式如下的 XML 文件:

<outer1>
    <inner1>
        <name>Stonecold</name>
        <profession>warrior</profession>
        <org>wwf</org>
    </inner1>
    <inner1>
        <name>Shanebond</name>
        <profession>Bowler</profession>
        <org>newzealand</org>
    </inner1>
    <inner1>
        <name>brain schemidit</name>
        <profession>Chairman</profession>
        <org>Google</org>
    </inner1>
</outer1>

我想将Shanebond 的值更改为Shane Bond

我使用的是XML::Simple,但结果是一个哈希。

我想要与输入文件相同的格式。例如:输出文件应该如下:

<outer1>
    <inner1>
        <name>Stonecold</name>
        <profession>warrior</profession>
        <org>wwf</org>
    </inner1>
    <inner1>
        <name>Shane Bond</name>
        <profession>Bowler</profession>
        <org>newzealand</org>
    </inner1>
    <inner1>
        <name>brain schemidit</name>
        <profession>Chairman</profession>
        <org>Google</org>
    </inner1>
</outer1>

请建议如何做到这一点。

提前致谢。

我希望将输出文件保存在同一目录中,并尽可能使用相同的名称。有可能吗?

【问题讨论】:

  • xml 文件是一个配置文件,使用它的组件无法读取哈希文件。此外,如果在创建文件后其格式发生更改,则组件也无法从配置文件中读取值
  • XMLin -> 处理内容 -> XMLout

标签: xml perl


【解决方案1】:

在读取或操作 XML 文件时,XML::Twig 通常是我希望使用的第一个工具。

起初我认为这可能超出了您的要求,但后来我注意到它确实带有 parsefile_inplace() 选项:

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

XML::Twig->new(
    pretty_print  => 'indented',
    twig_handlers => { 
        name => sub { 
            $_->set_text( 'Shane Bond' )->flush  if $_->text eq 'Shanebond' 
        },
    },
)->parsefile_inplace( 'data.xml', 'bak_*' );

注意。如果您不想保留备份文件,请删除第二个 arg ('bak_*')。

【讨论】:

    【解决方案2】:

    为什么要把它当作 XML 来处理呢?为什么不只做一个正则表达式替换?

    perl -pi -e 's/Shanebond/Shane Bond/' filename.xml
    

    这将完成替换,保持相同的文件名和所有内容。

    【讨论】:

      【解决方案3】:

      XML::Simple 具有允许您指定如何将输入转换为 Perl 数据结构以及如何输出该结构的选项:

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      
      use XML::Simple;
      
      my $xml_file = 'b.xml';
      
      my $xml = XMLin(
          $xml_file,
          KeepRoot => 1,
          ForceArray => 1,
      );
      
      $xml->{outer1}->[0]->{inner1}->[1]->{name} = 'Shane Bond';
      
      XMLout(
          $xml,
          KeepRoot => 1,
          NoAttr => 1,
          OutputFile => $xml_file,
      );
      

      XML::Simple 如果你做任何有趣的事情,确实会有点麻烦,因为它的目的不是成为一个通用的 XML 库,而是提供一种简单的方法来处理用 XML 编写的配置文件。

      CPAN 有大量的XML related modules。除非这是您必须处理的一次性问题,否则值得研究一些功能更强大、更适合的模块。

      【讨论】:

      • 我希望将输出文件保存在同一目录中,如果可能的话,使用相同的名称。有可能吗?
      • @pchakraborty 当然有可能。 Nifle甚至展示了如何做到这一点。文档清楚地解释了OutputFile。请偶尔阅读它们:它们有帮助。
      • 我试过这个并且它工作正常。我必须将它插入到主代码中,然后检查结果。感谢您的帮助。
      【解决方案4】:

      你试过XMLout with OutputFile

      来自 XML::Simple 的文档:

      XMLout() 的默认行为是将 XML 作为字符串返回。如果您希望将 XML 写入文件,只需使用“OutputFile”选项提供文件名。
      此选项还接受一个 IO 句柄对象 - 在 Perl 5.8.0 和更高版本中特别有用,用于使用 UTF-8 以外的编码进行输出,例如:

      open my $fh, '>:encoding(iso-8859-1)', $path or die "open($path): $!";
      XMLout($ref, OutputFile => $fh);
      

      【讨论】:

      • 我试过这个并且它工作正常。我必须将其插入主代码中,然后检查结果。感谢您的帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-05
      • 1970-01-01
      • 2021-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多