我有一个XML文件,如下图所示,我想从我的输出中删除hashref,Perldata,以及项目键值。我主要关注的是这个。
我有很多XML文件,如下图所示,其中有很多不同的变量,我想用一段代码来自动去除不必要的标签,而不需要在Perl代码中引入每个标签。
输入内容
<perldata>
<hashref memory_address="0xa7ab680">
<item key="employee">
<arrayref memory_address="0xa7dc1a8">
<item key="0">
<hashref memory_address="0xa7ab584">
<item key="age">
<hashref memory_address="0xa7ab338">
<item key="dob">10-02-2000</item>
</hashref>
</item>
<item key="department">
<hashref memory_address="0xa7ab1d0">
<item key="departmentname">Operations</item>
<item key="title">Manager</item>
</hashref>
</item>
<item key="location">
<hashref memory_address="0xa7ab068">
<item key="town">
<hashref memory_address="0xa7aaffc">
<item key="county">East</item>
<item key="name">Auchinleck</item>
</hashref>
</item>
</hashref>
</item>
<item key="name">
<hashref memory_address="0xa7ab518">
<item key="forename">John</item>
<item key="surname">Down</item>
</hashref>
</item>
<item key="************">M</item>
</hashref>
</item>
<item key="1">
<hashref memory_address="0xa7aae64">
<item key="age">
<hashref memory_address="0xa7aac90">
<item key="dob">05-03-2000</item>
</hashref>
</item>
<item key="department">
<hashref memory_address="0xa78c490">
<item key="departmentname">Internet</item>
<item key="title">Watcher</item>
</hashref>
</item>
<item key="location">
<hashref memory_address="0xa798da4">
<item key="town">
<hashref memory_address="0xa798d38">
<item key="county">South</item>
<item key="name">BB</item>
</hashref>
</item>
</hashref>
</item>
<item key="name">
<hashref memory_address="0xa7aadf8">
<item key="forename">Cr</item>
<item key="surname">Moral</item>
</hashref>
</item>
<item key="************">M</item>
</hashref>
</item>
</arrayref>
</item>
</hashref>
</perldata>
我的首选输出是。
<?xml version="1.0" encoding="UTF-8"?>
<data>
<employee>
<value name="************">M</value>
<age>
<dob>01-04-2000</dob>
</age>
<department>
<departmentname>Operations</departmentname>
<title>Manager</title>
</department>
<location>
<town>
<county>Somewhere</county>
<name>Someplace</name>
</town>
</location>
<name>
<forename>John</forename>
<surname>Down</surname>
</name>
</employee>
<employee>
<value name="************">M</value>
<age>
<dob>12-12-2000</dob>
</age>
<department>
<departmentname>Internet</departmentname>
<title>Researcher</title>
</department>
<location>
<town>
<county>Somewhere</county>
<name>Othertown</name>
</town>
</location>
<name>
<forename>Jane</forename>
<surname>Doe</surname>
</name>
</employee>
</data>
更新。 OP在回答问题时加入了这段代码(因为不是答案,所以被删除)。我把它稍微重新格式化了一下。
#!/usr/bin/perl -w
use strict;
use warnings;
use Data::Dumper;
use XML::Dumper;
use TAP3::Tap3edit;
$Data::Dumper::Indent=1;
$Data::Dumper::Useqq=1;
my $dump = new XML::Dumper;
use File::Basename;
my $perl = '';
my $xml = '';
my $tap3 = TAP3::Tap3edit->new();
foreach my $file(glob 'LB*')
{
my $files= basename($file);
my $filename=$files.".xml\n";
print $filename;
$tap3->decode($files) || die $tap3->error;
$perl = $tap3->structure;
$dump->pl2xml($perl, $filename);
}
看起来这是一个 已知问题 与模块。而鉴于这个bug是在2015年提出的,而且从2006年开始就没有新版本的模块,我猜测这个模块已经被放弃了,这个bug(连同 许多其他)是不会被修复的。
我建议寻找一个不同的XML处理模块。我喜欢 XML::LibXML (但我也听说了关于 XML::Twig).
我想简短的回答是 "不要使用XML::Dumper",你真正的问题是 "如何将Perl转储到XML?"。
这里有一点共同的问题。在你的Perlmonks帖子中 从XML文件中删除perldata,hashref。 (嗯,一定要注意,不管在哪里都有现成的讨论),你首先要解决数据结构的问题。但是,这其实不是你的问题,你的问题是要把Perl结构输出为XML。你提出的问题与你已经有的问题不同,这个问题有时被称为 XY问题. 这就是为什么这里的好问者往往总是问一些澄清的问题。
我的第一个想法是,你有一个Perl数据结构,我猜测是一个hash ref,你可以通过它来删除或修改你不想要的东西。
$perl = $tap3->structure;
你可以通过它来删除或修改任何你不想要的东西。这将是我的第一种方法,因为我可以使用基本的Perl功能来做这件事。如果你能给我们看一下那个数据结构,我们也许能想出一些简单的办法。
say Dumper( $perl );
看起来你看到的那些东西可能来自于... ... XML::Dumper所以你是通过使用一个差劲的工具来介绍的。我是在已经写好程序后才意识到这一点的,所以我想,你是免费得到的。
另外,如果你在别的地方发过问题,大多数人都希望你在问题中注明。我有点失望,我在这上面下了一些功夫,但已经有很多人在讨论了。从XML文件中删除perldata,hashref。 上的Perlmonks。
但是,由于我以前用苹果的属性列表(傻傻地用字典和数组做说那种通用结构)做过这种XML处理,所以这里有一个小的 XML::Twig 程序。我想这能让你达到大部分的目的,但我没有仔细检查输出。你可以用Twig来调整这个程序以适应你的口味。
XML::Twig 降到你的XML结构中。你可以为每一种节点定义 "处理程序"。这个处理程序是一个子程序引用,它可以获取当前节点在 $_
,Perl的主题变量。这个 perldata
处理程序很简单,因为它只是把名字改成了 data
借用 set_tag
:
perldata => sub { $_->set_tag( 'data' ) },
这个模块一开始有点吓人,因为你可以做的事情太多了,但是一旦你习惯了,你就拥有了一个非常强大的工具。
接下来的部分就比较复杂了。你想把所有的 hashref
和 arrayref
标签,并将其提升一个级别。
arrayref => \&move_up_children,
hashref => \&move_up_children,
这些标签会引用一个命名的子程序 move_up_children
所以我不会重复一堆代码。Twig的部分功能允许你 "剪切 "子节点并将其 "粘贴 "到其他节点中。在本例中,将子节点剪切到 hashref
或 arrayref
并将它们粘贴到任何包含 hashref
或 arrayref
. 然后,删除现在空的 hashref
或 arrayref
:
sub move_up_children {
my $parent = $_->parent;
for my $child ( $_->cut_children ) {
$child->paste( $parent );
}
$_->delete;
}
我不会去通过 item
处理。由于该标签有一个通用的用法,我需要测试我遇到了哪种用法。有四种情况。
********
价值arrayref
)而不是 employee
遗腹子 hashref
)employee
遗腹子 hashref
)arrayref
)#!perl
use v5.30;
use XML::Twig;
# just a way to get everything into one string
my $xml = do { local $/; <DATA> };
my $twig=XML::Twig->new(
twig_handlers =>
{
perldata => sub { $_->set_tag( 'data' ) },
arrayref => \&move_up_children,
hashref => \&move_up_children,
item => sub {
my $parent = $_->parent;
my $key = $_->{'att'}{'key'};
if( $key =~ m/\A \*+ \z/x ) {
$_->set_tag( 'value' );
$_->del_att( 'key' );
$_->set_att( name => $key );
}
elsif( $key =~ /\D/ and $key ne 'employee' ) {
$_->set_tag( $key );
$_->del_att( 'key' );
}
elsif( $key eq 'employee' ) {
local $_ = $_;
move_up_children();
}
else {
$_->set_tag( 'employee' );
$_->del_att( 'key' );
}
},
},
pretty_print => 'indented', # output will be nicely formatted
);
$twig->parse( $xml );
my $new_xml = $twig->toString;
say $new_xml;
sub move_up_children {
my $parent = $_->parent;
for my $child ( $_->cut_children ) {
$child->paste( $parent );
}
$_->delete;
}
__DATA__
<perldata>
<hashref memory_address="0xa7ab680">
<item key="employee">
<arrayref memory_address="0xa7dc1a8">
<item key="0">
<hashref memory_address="0xa7ab584">
<item key="age">
<hashref memory_address="0xa7ab338">
<item key="dob">10-02-2000</item>
</hashref>
</item>
<item key="department">
<hashref memory_address="0xa7ab1d0">
<item key="departmentname">Operations</item>
<item key="title">Manager</item>
</hashref>
</item>
<item key="location">
<hashref memory_address="0xa7ab068">
<item key="town">
<hashref memory_address="0xa7aaffc">
<item key="county">East</item>
<item key="name">Auchinleck</item>
</hashref>
</item>
</hashref>
</item>
<item key="name">
<hashref memory_address="0xa7ab518">
<item key="forename">John</item>
<item key="surname">Down</item>
</hashref>
</item>
<item key="************">M</item>
</hashref>
</item>
<item key="1">
<hashref memory_address="0xa7aae64">
<item key="age">
<hashref memory_address="0xa7aac90">
<item key="dob">05-03-2000</item>
</hashref>
</item>
<item key="department">
<hashref memory_address="0xa78c490">
<item key="departmentname">Internet</item>
<item key="title">Watcher</item>
</hashref>
</item>
<item key="location">
<hashref memory_address="0xa798da4">
<item key="town">
<hashref memory_address="0xa798d38">
<item key="county">South</item>
<item key="name">BB</item>
</hashref>
</item>
</hashref>
</item>
<item key="name">
<hashref memory_address="0xa7aadf8">
<item key="forename">Cr</item>
<item key="surname">Moral</item>
</hashref>
</item>
<item key="************">M</item>
</hashref>
</item>
</arrayref>
</item>
</hashref>
</perldata>
输出得到的东西很接近你想要的东西,也许有一些排序问题。
<data>
<employee>
<value name="************">M</value>
<name>
<surname>Moral</surname>
<forename>Cr</forename>
</name>
<location>
<town>
<name>BB</name>
<county>South</county>
</town>
</location>
<department>
<title>Watcher</title>
<departmentname>Internet</departmentname>
</department>
<age>
<dob>05-03-2000</dob>
</age>
</employee>
<employee>
<value name="************">M</value>
<name>
<surname>Down</surname>
<forename>John</forename>
</name>
<location>
<town>
<name>Auchinleck</name>
<county>East</county>
</town>
</location>
<department>
<title>Manager</title>
<departmentname>Operations</departmentname>
</department>
<age>
<dob>10-02-2000</dob>
</age>
</employee>
</data>