我已经在Perl中使用模块XML :: Twig几周了。到目前为止,我一直在将整个xml文件加载到内存中,然后编辑文件中的值。最后,我将文件保存为新名称以供进一步使用。
到目前为止,我一直在处理相当小的xml文件,但现在必须对一些非常大的xml文件(10 000+行)进行一些修改。
这些大型文件中有100个标签,但我只想修改10个标签。
有没有办法加载我需要修改的标签。更改标记值,然后将生成的更改保存到新的xml文件中,该文件包含原始文件但已修改10个标记的所有信息?
在XML :: Twig文档中看到有一些twig处理程序只能加载到xml文档的一部分,但是在我尝试修改几个标记的示例中,只有那些修改过的部分作为xml返回文件和其他信息丢失!这对我没有好处。
以下是我正在处理的示例结构
<datatag1 a="1A">
<t>A</t>
</datatag1>
<datatag1 a="B2">
<t>D</t>
</datatag1>
<datatag1 a="3C">
<t>1</t>
</datatag1>
<datatag1 a="4S3">
<t>14</t>
</datatag1>
<datatag1 a="5AA3">
<t>1</t>
</datatag1>
我想要做的是改变datatag1的子t值,比方说,从A到B,其中a =“1A”。那么我的修改后的xml将是:
<datatag1 a="1A">
<t>B</t>
</datatag1>
<datatag1 a="B2">
<t>D</t>
</datatag1>
<datatag1 a="3C">
<t>1</t>
</datatag1>
<datatag1 a="4S3">
<t>14</t>
</datatag1>
<datatag1 a="5AA3">
<t>1</t>
</datatag1>
此外,我有一个包含一组键的哈希,列出了我想要修改的“a”值。哈希值给出了我想插入的新“t”值。
如果您需要任何进一步的信息或任何不清楚的地方,请告诉我。
答案 0 :(得分:2)
是的,您绝对可以使用XML::Twig
执行此操作。
核心观点是,twig_handler
会在解析发生时触发。但是,要输出“故事到目前为止”,您需要flush
- 或者purge
。
#!/usr/bin/env perl
use warnings;
use strict;
use XML::Twig;
sub modify_datatag {
my ( $twig, $datatag ) = @_;
if ( $datatag -> att('a') eq '1A' ) {
$datatag -> first_child('t') -> set_text('new text here');
}
#delete this, as it breaks the XML. But you get the point.
print "\n## flushing twig from memory\n";
$twig -> flush;
}
my $xml = XML::Twig -> new ( 'twig_handlers' => { 'datatag1' => \&modify_datatag } );
$xml -> parse ( \*DATA );
$xml -> flush;
__DATA__
<xml>
<datatag1 a="1A">
<t>B</t>
</datatag1>
<datatag1 a="B2">
<t>D</t>
</datatag1>
<datatag1 a="3C">
<t>1</t>
</datatag1>
<datatag1 a="4S3">
<t>14</t>
</datatag1>
<datatag1 a="5AA3">
<t>1</t>
</datatag1>
</xml>
每次调用flush
时,到目前为止的进度都会输出到文件中。仍在处理的任何标签(例如,未关闭)将保留在存储器中。
你可以改为purge
,但这会丢弃。
以上打印到STDOUT
- 但您可以使用parsefile_inplace
重写现有文件。
您还可以为flush
指定一个文件句柄参数,以便...执行它在锡上所说的内容。