Para responder a essa pergunta corretamente, seria ideal que precisássemos de um exemplo melhor - um xml válido é um bom começo.
Além disso - um exemplo de saída desejada. Você não indica, por exemplo, onde deseja que os elementos <C>
e <D>
terminem em seu XML resultante. Eles são já filhos de <B>
- você deseja preservar B
ou reparent C
e D
na raiz?
No entanto, reconstruir genericamente XML
é bastante fácil usando XML::Twig
e perl
.
Por exemplo Assim:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my @wanted = qw ( C D id );
my %wanted = map { $_ => 1 } @wanted;
sub delete_unwanted_tags {
my ( $twig, $element ) = @_;
my $tag = $element -> tag;
if ( not $wanted{$tag} ) {
$element -> delete;
}
}
my $twig = XML::Twig -> new ( twig_handlers => { _all_ => \&delete_unwanted_tags } );
$twig -> parse ( \*DATA );
$twig -> print;
__DATA__
<A>
<id>123</id>
<B>
<C>value1</C>
<D>value2</D>
<E></E>
</B>
<Z></Z>
<Y></Y>
</A>
Como ainda não dissemos "keep <B>
", o resultado é:
<A>
<id>123</id>
</A>
Adicionando <B>
à lista wanted
:
<A>
<id>123</id>
<B>
<C>value1</C>
<D>value2</D>
</B>
</A>
Se, no entanto, o que você deseja fazer é reparent C
e D
into A
:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
my @wanted = qw ( id);
my @reparent = qw ( C D );
#turn the above into hashes, so we can do "if $wanted{$tag}"
my %wanted = map { $_ => 1 } @wanted;
my %reparent = map { $_ => 1 } @reparent;
sub delete_unwanted_tags {
my ( $twig, $element ) = @_;
my $tag = $element->tag;
if ( not $wanted{$tag} ) {
$element->delete;
}
if ( $reparent{$tag} ) {
$element->move( 'last_child', $twig->root );
}
}
my $twig = XML::Twig->new(
pretty_print => 'indented_a',
twig_handlers => { _all_ => \&delete_unwanted_tags }
);
$twig->parse( \*DATA );
$twig->print;
__DATA__
<A>
<id>123</id>
<B>
<C>value1</C>
<D>value2</D>
<E></E>
</B>
<Z></Z>
<Y></Y>
</A>
Observação - o "manipulador de ramificação" é chamado no fim de cada elemento (quando uma tag de fechamento é encontrada) e é por isso que funciona - recursamos para encontrar C
e D
antes de terminarmos o processamento (e a exclusão) B
.
Isso produz:
<A>
<id>123</id>
<C>value1</C>
<D>value2</D>
</A>
Acima, usei __DATA__
, \*DATA
e parse
porque permite ilustrar o XML e as técnicas. Você provavelmente deve usar em vez de parsefile('my_file.xml')
em vez de parse(\*DATA)
.