How to change namespace and uri to new one with perl? Files are big (20 MB) and containing one line and the structures are complicated. Example:
<?xml version="1.0" encoding="utf-8"?>
<m:sr xmlns:m="http://www.example.com/mmm" xml:lang="et">
<m:A m:AS="EX" m:KF="sss1">
<m:m m:u="uus" m:O="ggg">ggg</m:m>
</m:A>
</m:sr>
To:
<?xml version="1.0" encoding="utf-8"?>
<a:sr xmlns:a="http://www.example.com/aaa" xml:lang="et">
<a:A a:AS="EX" a:KF="sss1">
<a:m a:u="uus" a:O="ggg">ggg</a:m>
</a:A>
</a:sr>
You can do this with XML::Twig.
The code below is quite clean in that it makes very few assumptions about the input, notably it relies on the URI of the namespace in the input, not on the prefix. The twig is flushed every time any element is done parsing, so it keeps very little in memory.
#!/usr/bin/perl
use strict;
use warnings;
use XML::Twig;
# parameters, may be changed
my $SR = 'sr'; # local name of the root of the fragment
my $OUT = 'a'; # prefix in the output
my $IN_NS = 'http://www.example.com/mmm'; # namespace URIs
my $OUT_NS = 'http://www.example.com/aaa';
my $t= XML::Twig->new(
map_xmlns => { $IN_NS => $OUT, $OUT_NS => $OUT, },
start_tag_handlers => { "$OUT:$SR" => \&change_ns_decl, },
twig_handlers => { _all_ => sub { $_->flush; }, },
keep_spaces => 1,
)
->parse( \*DATA); # replace by parsefile( "my.xml");
exit;
sub change_ns_decl
{ my( $t, $sr)= @_;
$sr->set_att( "xmlns:$OUT" => $OUT_NS);
}
__DATA__
<?xml version="1.0" encoding="utf-8"?>
<m:sr xml:lang="et" xmlns:m="http://www.example.com/mmm">
<m:A m:AS="EX" m:KF="sss1">
<m:m m:u="uus" m:O="ggg">ggg</m:m>
</m:A>
</m:sr>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With