Perl 使用XML::Twig复制XML值
我有嵌套的XML标记,需要使用XML::Twig将产品XML中的ExternalId值转换为ProductPageURL标记 你能告诉我如何使代码更简单吗?我无法达到预期的结果。这里有一种方法:Perl 使用XML::Twig复制XML值,perl,xml-parsing,xml-twig,Perl,Xml Parsing,Xml Twig,我有嵌套的XML标记,需要使用XML::Twig将产品XML中的ExternalId值转换为ProductPageURL标记 你能告诉我如何使代码更简单吗?我无法达到预期的结果。这里有一种方法: use warnings; use strict; use XML::Twig; my $twig = XML::Twig->new( twig_handlers => { Product => \&prod, }, pr
use warnings;
use strict;
use XML::Twig;
my $twig = XML::Twig->new(
twig_handlers => {
Product => \&prod,
},
pretty_print => 'indented',
keep_encoding => 1,
);
$twig->parse(q(
<Products>
<Product>
<ExternalId>317851</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>316232</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>13472</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
</Products>
));
$twig->print();
sub prod {
my ($t, $prod) = @_;
my $extid = $prod->first_child('ExternalId');
my $id = $extid->text();
$extid->prefix('PF');
my $url = $prod->first_child('ProductPageUrl');
$url->set_text($id);
}
输出
这里有一个方法:
use warnings;
use strict;
use XML::Twig;
my $twig = XML::Twig->new(
twig_handlers => {
Product => \&prod,
},
pretty_print => 'indented',
keep_encoding => 1,
);
$twig->parse(q(
<Products>
<Product>
<ExternalId>317851</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>316232</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>13472</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
</Products>
));
$twig->print();
sub prod {
my ($t, $prod) = @_;
my $extid = $prod->first_child('ExternalId');
my $id = $extid->text();
$extid->prefix('PF');
my $url = $prod->first_child('ProductPageUrl');
$url->set_text($id);
}
输出
您的初始代码中有两个问题:首先,我不认为get是XML::Twig::Elt方法。然后,首先为外部文本添加前缀,然后在添加前缀后尝试使用它更新ProductPageUrl。那不行。在这种情况下,我认为最好为产品标签使用一个处理程序,在其中获取id数据,然后更新两个子元素 这里有一个解决方案,作为测试编写,以便在输出更改时更容易更新:
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 1;
use XML::Twig;
# in and expected are in the DATA section, separated by 2 \n
my( $in, $expected)= do { local $/="\n\n"; <DATA>};
my $t= XML::Twig->new( twig_handlers => { Product => \&update_product },
keep_spaces => 1,
)
->parse( $in);
is( $t->sprint, $expected, "one test to rule them all");
sub update_product
{ my( $t, $product)= @_;
my $id= $product->field( 'ExternalId');
$product->first_child( 'ExternalId')->prefix( 'PF');
$product->first_child( 'ProductPageUrl')->set_text( $id);
}
__DATA__
<Products>
<Product>
<ExternalId>317851</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>316232</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>13472</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
</Products>
<Products>
<Product>
<ExternalId>PF317851</ExternalId>
<ProductPageUrl>317851</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF316232</ExternalId>
<ProductPageUrl>316232</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF13472</ExternalId>
<ProductPageUrl>13472</ProductPageUrl>
</Product>
</Products>
您的初始代码中有两个问题:首先,我不认为get是XML::Twig::Elt方法。然后,首先为外部文本添加前缀,然后在添加前缀后尝试使用它更新ProductPageUrl。那不行。在这种情况下,我认为最好为产品标签使用一个处理程序,在其中获取id数据,然后更新两个子元素 这里有一个解决方案,作为测试编写,以便在输出更改时更容易更新:
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 1;
use XML::Twig;
# in and expected are in the DATA section, separated by 2 \n
my( $in, $expected)= do { local $/="\n\n"; <DATA>};
my $t= XML::Twig->new( twig_handlers => { Product => \&update_product },
keep_spaces => 1,
)
->parse( $in);
is( $t->sprint, $expected, "one test to rule them all");
sub update_product
{ my( $t, $product)= @_;
my $id= $product->field( 'ExternalId');
$product->first_child( 'ExternalId')->prefix( 'PF');
$product->first_child( 'ProductPageUrl')->set_text( $id);
}
__DATA__
<Products>
<Product>
<ExternalId>317851</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>316232</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>13472</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
</Products>
<Products>
<Product>
<ExternalId>PF317851</ExternalId>
<ProductPageUrl>317851</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF316232</ExternalId>
<ProductPageUrl>316232</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF13472</ExternalId>
<ProductPageUrl>13472</ProductPageUrl>
</Product>
</Products>
<Products>
<Product>
<ExternalId>PF317851</ExternalId>
<ProductPageUrl>317851</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF316232</ExternalId>
<ProductPageUrl>316232</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF13472</ExternalId>
<ProductPageUrl>13472</ProductPageUrl>
</Product>
</Products>
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 1;
use XML::Twig;
# in and expected are in the DATA section, separated by 2 \n
my( $in, $expected)= do { local $/="\n\n"; <DATA>};
my $t= XML::Twig->new( twig_handlers => { Product => \&update_product },
keep_spaces => 1,
)
->parse( $in);
is( $t->sprint, $expected, "one test to rule them all");
sub update_product
{ my( $t, $product)= @_;
my $id= $product->field( 'ExternalId');
$product->first_child( 'ExternalId')->prefix( 'PF');
$product->first_child( 'ProductPageUrl')->set_text( $id);
}
__DATA__
<Products>
<Product>
<ExternalId>317851</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>316232</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
<Product>
<ExternalId>13472</ExternalId>
<ProductPageUrl></ProductPageUrl>
</Product>
</Products>
<Products>
<Product>
<ExternalId>PF317851</ExternalId>
<ProductPageUrl>317851</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF316232</ExternalId>
<ProductPageUrl>316232</ProductPageUrl>
</Product>
<Product>
<ExternalId>PF13472</ExternalId>
<ProductPageUrl>13472</ProductPageUrl>
</Product>
</Products>