XML :: Twig使用twig处理程序或twig root来更新xml文件的一部分

时间:2018-03-21 15:59:34

标签: xml perl xml-twig

我已经在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”值。

如果您需要任何进一步的信息或任何不清楚的地方,请告诉我。

1 个答案:

答案 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指定一个文件句柄参数,以便...执行它在锡上所说的内容。