在以下数据文件中,我想将每个<Field>
标记视为<Register>
的子标记,将每个<Register>
视为<Partition>
的子标记。所以,基本上,我正在尝试使用相应的<Partition>
和<Register>
提取每个<Field>
详细信息。由于所有这些标签都是独立的而不是父子关系,我如何获得所需的输出?
由于文件非常大,我不想将其作为子父关系,因为它需要查找/替换和手动干预。
<Partition>
<Name>1</Name>
<Abstract>2</Abstract>
<Description>3</Description>
<ParentName>4</ParentName>
</Partition>
<Partition>
<Name>8</Name>
<Abstract></Abstract>
<Description>9</Description>
<ParentName>10</ParentName>
</Partition>
<Register>
<Name>12</Name>
<Abstract></Abstract>
<Description>13</Description>
<ParentName>14</ParentName>
<Size>32</Size>
<AccessMode>15</AccessMode>
<Type>16</Type>
</Register>
<Field>
<Name>17</Name>
<Abstract></Abstract>
<Description></Description>
<ParentName></ParentName>
</Field>
<Field>
.
.
.
</Field>
<Register>
.
.
.
</Register>
<Field>
.
.
.
</Field>
<Field>
.
.
.
</Field>
<Partition>
<Name>88</Name>
<Abstract></Abstract>
<Description></Description>
<ParentName>55</ParentName>
</Partition>
<Register>
.
.
.
</Register>
<Field>
.
.
.
</Field>
<Partition>
.
.
.
</Partition>
<Partition>
.
.
.
</Partition>
<Partition>
.
.
.
</Partition>
<Register>
.
.
.
</Register>
我正在使用XML::Twig
包,这是我的代码段:
foreach my $register ( $twig->get_xpath('//Register') ) # get each <Register>
{
#print $register, "\n";
my $reg_name = $register->first_child('Name')->text;
my $reg_abstract= $register->first_child('Abstract')->text;
my $reg_description= $register->first_child('Description')->text;
.
.
.
foreach my $xml_field ($register->get_xpath('Field'))
{
my $reg_field_name= $xml_field->first_child('Name')->text;
my $reg_field_abstract= $xml_field->first_child('Abstract')->text;
#print "$reg_field_name \n";
.
.
.
}
}
答案 0 :(得分:0)
根据您的评论,如果您想要将Register
和Field
元素作为Partition
元素的子元素重写文件,则可以执行以下操作:
最简单的解决方案,整个文件加载到内存中:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $test_file= 'test.xml';
XML::Twig->new( twig_handlers => { 'Register|Field' => \&child,
},
pretty_print => 'indented',
)
->parsefile( $test_file)
->print;
sub child
{ my( $t, $child)= @_;
$child->move( last_child => $child->prev_sibling( 'Partition'));
}
由于您提到文件可能非常大,下面是一个稍微复杂的版本,只保留在内存中的2 Partition
个元素(包括第一个的新子元素)。解析Partition
后,它会使用flush_up_to
来刷新树,直至上一个Partition
:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $test_file= 'test.xml';
XML::Twig->new( twig_handlers => { 'Partition' => \&parent,
'Register|Field' => \&child,
},
pretty_print => 'indented',
)
->parsefile( $test_file);
sub child
{ my( $t, $child)= @_;
$child->move( last_child => $child->prev_sibling( 'Partition'));
}
sub parent
{ my( $t, $partition)= @_;
if( my $prev_partition = $partition->prev_sibling( 'Partition'))
{ $t->flush_up_to( $prev_partition); }
}
请注意,由于使用了flush_up_to
,因此在解析结束时会自动刷新树的其余部分
如果您需要将XML写入特定文件而不是STDOUT,您还可以将文件句柄传递给flush_up_to
。
答案 1 :(得分:0)
顺便说一句,我已经编写了非常基本的代码,可以将Register
作为孩子转换为Register
,将Partition
作为孩子转换为use strict;
#use warnings;
use XML::Twig;
use Data::Dumper;
use Data::Alias;
my $input_xml_file = "gpon.xml";
open (IN_FILE,$input_xml_file);
my @input_file = <IN_FILE>;
for (my $line=0;$line<@input_file;$line++)
{
if ($input_file[$line] =~ /<\/Partition>/ && $input_file[$line+1] =~ /<Register>/)
{
$input_file[$line] = '';
}
if ($input_file[$line] =~ /<\/Field>/ && $input_file[$line+1] =~ /<Partition>/)
{
$input_file[$line] = "</Field>
</Register>
</Partition>
";
}
if ($input_file[$line] =~ /<\/Field>/ && $input_file[$line+1] =~ /<Register>/)
{
$input_file[$line] = "</Field>
</Register>
";
}
if ($input_file[$line] =~ /<\/Register>/ && $input_file[$line+1] =~ /<Field>/ )
{
$input_file[$line] = '';
}
}
#print OUT_FILE "</Register>";
close(IN_FILE);
open (OUT_FILE,'>gpon_modified.xml');
foreach (@input_file)
{
print OUT_FILE "$_";
}
print OUT_FILE "</Register>
</Partition>";
close (OUT_FILE);
:
$df.printSchema()
root
|-- ACTION: string (nullable = true)
$df_new.select(["ACTION"]).show()
AnalysisException: "Reference 'ACTION' is ambiguous, could be: ACTION#22058, ACTION#22334