【问题标题】:Perl: Saving edited fields into the same XML filePerl:将编辑的字段保存到同一个 XML 文件中
【发布时间】:2012-04-25 17:38:20
【问题描述】:

我 1 周前刚开始使用 Perl,我是一名编程新手。请帮助,因为我的公司项目依赖于此。

情况:

我想打开一个 XML 文件,在本例中是 Library.xml,并使用特定的“ISBN”编号编辑 XML 文档。找到 ISBN 编号后,我想更改具有匹配“ISBN”编号的特定书籍的页数。

问题:

现在,我可以执行上述操作了,但是我需要使用相同的名称“library.xml”保存更新的 XML,并且还要保持原始 XML 文档的 XML 结构。这就是我难住的地方。我尝试过使用 XML::DUMPER 和 XML::TWIG 以及其他可能的方法,但都失败了。

原始 XML 文档:

library.XML 如下所示:

<library>
  <book>
    <title>Perl Best Practices</title>
    <author>Damian Conway</author>
    <isbn>0596001738</isbn>
    <pages>542</pages>
    <image src="http://www.oreilly.com/catalog/covers/perlbp.s.gif"
           width="145" height="190" />
  </book>
  <book>
    <title>Perl Cookbook, Second Edition</title>
    <author>Tom Christiansen</author>
    <author>Nathan Torkington</author>
    <isbn>0596003137</isbn>
    <pages>964</pages>
    <image src="http://www.oreilly.com/catalog/covers/perlckbk2.s.gif"
           width="145" height="190" />
  </book>
  <book>
    <title>Guitar for Dummies</title>
    <author>Mark Phillips</author>
    <author>John Chappell</author>
    <isbn>076455106X</isbn>
    <pages>392</pages>
    <image src="http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg"
         width="100" height="125" />
  </book>
</library> 

守则:

以下是我试图操作但没有成功的代码。

#!/usr/bin/perl

use strict;
use warnings;
#use XML::Simple qw(:strict);

use XML::LibXML;
use XML::Dumper;

my $dump = new XML::Dumper;

my $perl = ' ';
my $xml  = $dump->pl2xml( $perl );

my $filename = 'library.xml';

my $isbn   = '0596001738';

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_file($filename);

my $query  = "//book[isbn = '$isbn']/pages/text()";

my($node)  = $doc->findnodes($query);
$node->setData('99999');

$perl = $doc->toString;

$xml = $dump->pl2xml( $perl, "library.xml" ); 

print $doc->toString;

输出:

以下是我的输出。输出与原始 XML 文档不同。

<perldata>
<scalar>&lt;xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;&gt;
&lt;library&gt;
  &lt;book&gt;
    &lt;title&gt;Perl Best Practices&lt;/title&gt;
    &lt;author&gt;Damian Conway&lt;/author&gt;
    &lt;isbn&gt;0596001738&lt;/isbn&gt;
    &lt;pages&gt;99999&lt;/pages&gt;
    &lt;image src=&quot;http://www.oreilly.com/catalog/covers/perlbp.s.gif&quot; width=&quot;145&quot; height=&quot;190&quot;/&gt;
  &lt;/book&gt;
  &lt;book&gt;
    &lt;title&gt;Perl Cookbook, Second Edition&lt;/title&gt;
    &lt;author&gt;Tom Christiansen&lt;/author&gt;
    &lt;author&gt;Nathan Torkington&lt;/author&gt;
    &lt;isbn&gt;0596003137&lt;/isbn&gt;
    &lt;pages&gt;964&lt;/pages&gt;
    &lt;image src=&quot;http://www.oreilly.com/catalog/covers/perlckbk2.s.gif&quot; width=&quot;145&quot; height=&quot;190&quot;/&gt;
  &lt;/book&gt;
  &lt;book&gt;
    &lt;title&gt;Guitar for Dummies&lt;/title&gt;
    &lt;author&gt;Mark Phillips&lt;/author&gt;
    &lt;author&gt;John Chappell&lt;/author&gt;
    &lt;isbn&gt;076455106X&lt;/isbn&gt;
    &lt;pages&gt;392&lt;/pages&gt;
    &lt;image  src=&quot;http://media.wiley.com/product_data/coverImage/6X/07645510/076455106X.jpg&quot;  width=&quot;100&quot; height=&quot;125&quot;/&gt;
  &lt;/book&gt;
&lt;/library&gt;
  </scalar>
</perldata>

【问题讨论】:

标签: xml perl


【解决方案1】:

您没有充分的理由混合 XML 模块 - 编程的第一步是了解您在做什么,您不能只是将代码放在一起并期望它以某种方式实现您的意思。

从你的程序中删除 18 行后,代码如下所示,并且运行良好:

#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;

my $filename = 'library.xml';
my $isbn   = '0596001738';

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_file($filename);
my $query  = "//book[isbn = '$isbn']/pages/text()";
my($node)  = $doc->findnodes($query);
$node->setData('99999');
print $doc->toString;

唯一缺少的是将更改后的文档写回文件中:

$doc->toFile('library.xml');

【讨论】:

  • 感谢您的建议。成功地完成了任务。将听取您关于学习 perl 的建议。再次感谢。
【解决方案2】:

XML::Twig 解决方案:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Twig;

# That's probably not how you get the data
my %isbn_to_pages= ( '0596001738' => 999, 
                     '076455106X' => 123,
                   );

XML::Twig->new( twig_handlers => { book => \&book },
                keep_spaces => 1,
              )
            # the second argument creates a backup file book_data.xml.bak
          ->parsefile_inplace( 'book_data.xml', '.bak'); 


sub book
  { my( $t, $book)= @_;
    my $isbn= $book->field( 'isbn');
    if( my $pages= $isbn_to_pages{$isbn})
      { $_->first_child( 'pages')->set_text( $pages); }
    $t->flush;
  }

【讨论】:

  • 解决办法可以保存文件。请问,上面哪个命令真正打开了原始的XML?感谢您的帮助...
  • 来自文档:parsefile_inplace“就地”解析和更新文件。它通过创建一个临时文件,选择它作为 print() 语句(和方法)的默认值,然后解析输入文件来做到这一点。如果解析成功,则移动临时文件以替换输入文件。
猜你喜欢
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
  • 2023-03-28
  • 2011-01-05
  • 2014-02-18
  • 1970-01-01
  • 2013-02-01
  • 1970-01-01
相关资源
最近更新 更多