使用 Strawberry Perl 和 twig 清除 Windows 目录树中所有文件中 xml 括号中的内容
Clear content in xml brackets in all files in directory tree on Windows using Strawberry Perl and twig
我想清除目录树中 XML 文件中 <loot>
</loot>
元素内的全部内容。我正在为 windows 64 位使用 Strawberry Perl。
例如这个 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon"/>
<health="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
<item id="1"/>
<item id="3"/>
<inside>
<item id="6"/>
</inside>
</item>
</loot>
更改后的文件应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon"/>
<health="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
</loot>
我有这个代码:
#!/usr/bin/perl
use warnings;
use strict;
use File::Find::Rule;
use XML::Twig;
sub delete_loot {
my ( $twig, $loot ) = @_;
foreach my $loot_entry ( $loot -> children ) {
$loot_entry -> delete;
}
$twig -> flush;
}
my $twig = XML::Twig -> new ( pretty_print => 'indented',
twig_handlers => { 'loot' => \&delete_loot } );
foreach my $file ( File::Find::Rule -> file()
-> name ( '*.xml' )
-> in ( 'C:\Users\PIO\Documents\serv\monsters' ) ) {
print "Processing $file\n";
$twig -> parsefile_inplace($file);
}
但它只正确编辑它遇到的第一个文件,其余文件保持清晰(0 kb 清晰文件)
注意 flush
更改为 print
问题中的代码对我有效(有效 XML)。
不过,我还是推荐以下任何一个版本。使用两组有效 XML 文件进行测试。
当先设置 XML::Twig->new(...)
然后循环处理文件时,我得到了相同的行为。第一个文件处理正确,其他文件完全空白。 编辑 当 flush
替换为 print
时,显示的代码实际上有效(具有正确的 XML 文件)。但是我仍然建议使用以下任一版本,因为 XML::Twig
不能很好地支持多个文件。
原因可能与new
是class方法有关。但是,我不明白为什么这需要影响多个文件的处理。
回调安装在循环之外,但我已经测试过为每个文件重新安装它并且它没有帮助。
最后,通过清除状态(由 class 方法创建,虽然这里显然很痛,但不需要 flush
-ing new
)。这不影响下面的代码,但它仍然被替换为 print
.
然后循环执行所有操作。一个简单的版本
use strict;
use warnings;
use File::Find::Rule;
use XML::Twig;
my @files = File::Find::Rule->file->name('*.xml')->in('...');
foreach my $file (@files)
{
print "Processing $file\n";
my $t = XML::Twig->new(
pretty_print => 'indented',
twig_handlers => { loot => \&clear_elt },
);
$t->parsefile_inplace($file)->print;
}
sub clear_elt {
my ($t, $elt) = @_;
my $elt_name = $elt->name; # get the name
my $parent = $elt->parent; # fetch the parent
$elt->delete; # remove altogether
$parent->insert_new_elt($elt_name, ''); # add it back empty
}
回调代码被简化,完全删除元素然后添加回来,空的。请注意,sub 不需要 对元素名称进行硬编码。因此,这可以用来删除任何元素。
我们可以通过使用另一种class方法nparse
.
来避免在循环中调用new
my $t = XML::Twig->new( pretty_print => 'indented' );
foreach my $file (@files)
{
print "Processing $file\n";
my $tobj = XML::Twig->nparse(
twig_handlers => { loot => \&clear_elt },
$file
);
$tobj->parsefile_inplace($file)->print;
}
# the sub clear_elt() same as above
我们必须首先调用new
构造函数,即使它没有直接在循环中使用。
请注意,在循环 之前调用 new
而不是 twig_handlers
然后在内部设置处理程序
$t->setTwigHandlers(loot => sub { ... });
没有帮助。我们仍然只正确处理了第一个文件。
XML::Twig doc 表示 "Multiple twigs are not well supported"。
如果您查看 twig 对象的状态(例如使用 Data::Dumper),您会发现第一个和随后的 运行 之间存在很大差异。看起来它认为它已经被完全刷新了(这是真的,因为在第一个 运行 期间有一个完全刷新)。它可能没有更多要打印的后续文件,文件最终为空。
在每个循环中重新创建树枝对象对我有用:
#!/usr/bin/perl
use warnings;
use strict;
use File::Find::Rule;
use XML::Twig;
sub delete_loot {
my ( $twig, $loot ) = @_;
foreach my $loot_entry ( $loot -> children ) {
$loot_entry -> delete;
}
}
foreach my $file ( File::Find::Rule -> file()
-> name ( '*.xml' )
-> in ( '/home/dabi/tmp' ) ) {
print "Processing $file\n";
my $twig = XML::Twig -> new ( pretty_print => 'indented',
twig_handlers => { loot => \&delete_loot, } );
$twig -> parsefile($file);
$twig -> print_to_file($file);
}
此外,我必须更改 XML 文件结构才能对其进行处理:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon">
<health value="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
<item id="1"/>
<item id="3">
<inside>
<item id="6"/>
</inside>
</item>
</loot>
</monster>
我想清除目录树中 XML 文件中 <loot>
</loot>
元素内的全部内容。我正在为 windows 64 位使用 Strawberry Perl。
例如这个 XML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon"/>
<health="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
<item id="1"/>
<item id="3"/>
<inside>
<item id="6"/>
</inside>
</item>
</loot>
更改后的文件应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon"/>
<health="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
</loot>
我有这个代码:
#!/usr/bin/perl
use warnings;
use strict;
use File::Find::Rule;
use XML::Twig;
sub delete_loot {
my ( $twig, $loot ) = @_;
foreach my $loot_entry ( $loot -> children ) {
$loot_entry -> delete;
}
$twig -> flush;
}
my $twig = XML::Twig -> new ( pretty_print => 'indented',
twig_handlers => { 'loot' => \&delete_loot } );
foreach my $file ( File::Find::Rule -> file()
-> name ( '*.xml' )
-> in ( 'C:\Users\PIO\Documents\serv\monsters' ) ) {
print "Processing $file\n";
$twig -> parsefile_inplace($file);
}
但它只正确编辑它遇到的第一个文件,其余文件保持清晰(0 kb 清晰文件)
注意 flush
更改为 print
问题中的代码对我有效(有效 XML)。
不过,我还是推荐以下任何一个版本。使用两组有效 XML 文件进行测试。
当先设置 XML::Twig->new(...)
然后循环处理文件时,我得到了相同的行为。第一个文件处理正确,其他文件完全空白。 编辑 当 flush
替换为 print
时,显示的代码实际上有效(具有正确的 XML 文件)。但是我仍然建议使用以下任一版本,因为 XML::Twig
不能很好地支持多个文件。
原因可能与new
是class方法有关。但是,我不明白为什么这需要影响多个文件的处理。
回调安装在循环之外,但我已经测试过为每个文件重新安装它并且它没有帮助。
最后,通过清除状态(由 class 方法创建,虽然这里显然很痛,但不需要 flush
-ing new
)。这不影响下面的代码,但它仍然被替换为 print
.
然后循环执行所有操作。一个简单的版本
use strict;
use warnings;
use File::Find::Rule;
use XML::Twig;
my @files = File::Find::Rule->file->name('*.xml')->in('...');
foreach my $file (@files)
{
print "Processing $file\n";
my $t = XML::Twig->new(
pretty_print => 'indented',
twig_handlers => { loot => \&clear_elt },
);
$t->parsefile_inplace($file)->print;
}
sub clear_elt {
my ($t, $elt) = @_;
my $elt_name = $elt->name; # get the name
my $parent = $elt->parent; # fetch the parent
$elt->delete; # remove altogether
$parent->insert_new_elt($elt_name, ''); # add it back empty
}
回调代码被简化,完全删除元素然后添加回来,空的。请注意,sub 不需要 对元素名称进行硬编码。因此,这可以用来删除任何元素。
我们可以通过使用另一种class方法nparse
.
new
my $t = XML::Twig->new( pretty_print => 'indented' );
foreach my $file (@files)
{
print "Processing $file\n";
my $tobj = XML::Twig->nparse(
twig_handlers => { loot => \&clear_elt },
$file
);
$tobj->parsefile_inplace($file)->print;
}
# the sub clear_elt() same as above
我们必须首先调用new
构造函数,即使它没有直接在循环中使用。
请注意,在循环 之前调用 new
而不是 twig_handlers
然后在内部设置处理程序
$t->setTwigHandlers(loot => sub { ... });
没有帮助。我们仍然只正确处理了第一个文件。
XML::Twig doc 表示 "Multiple twigs are not well supported"。
如果您查看 twig 对象的状态(例如使用 Data::Dumper),您会发现第一个和随后的 运行 之间存在很大差异。看起来它认为它已经被完全刷新了(这是真的,因为在第一个 运行 期间有一个完全刷新)。它可能没有更多要打印的后续文件,文件最终为空。
在每个循环中重新创建树枝对象对我有用:
#!/usr/bin/perl
use warnings;
use strict;
use File::Find::Rule;
use XML::Twig;
sub delete_loot {
my ( $twig, $loot ) = @_;
foreach my $loot_entry ( $loot -> children ) {
$loot_entry -> delete;
}
}
foreach my $file ( File::Find::Rule -> file()
-> name ( '*.xml' )
-> in ( '/home/dabi/tmp' ) ) {
print "Processing $file\n";
my $twig = XML::Twig -> new ( pretty_print => 'indented',
twig_handlers => { loot => \&delete_loot, } );
$twig -> parsefile($file);
$twig -> print_to_file($file);
}
此外,我必须更改 XML 文件结构才能对其进行处理:
<?xml version="1.0" encoding="UTF-8"?>
<monster name="Dragon">
<health value="10000"/>
<immunities>
<immunity fire="1"/>
</immunities>
<loot>
<item id="1"/>
<item id="3">
<inside>
<item id="6"/>
</inside>
</item>
</loot>
</monster>