문제

I am attempting to use XML::Simple to update a few Java applications' server.xml files. While I am able to parse and update the object fine, the output from XMLout is giving me some trouble. It seems to insist on expanding all the original attributes into single elements which confuses my Java application when it starts up.

Here is an example of part of the XML:

<Server port="9000" shutdown="SHUTDOWN">
<Service name="Catalina">
<Connector port="9002" redirectPort="8443" enableLookups="false" protocol="AJP/1.3"     URIEncoding="UTF-8"/>
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
</Service>
</Server>  

Me making a small change via XMLin:

$xml->XMLin("server.xml", ForceArray => ['Connector']);
$server_xml->{'port'} = $server_port;
$server_xml->{'Service'}->{'Connector'}->[0]->{'port'} = $http_port;

I then output my file like this:

XMLout($server_xml, RootName => 'Server',  KeepRoot => 0, NoAttr => 1, OutputFile => "server.xml");

Everything seems to work fine and look good in Data::Dumper but when I look at my output I now have XML like this:

   <Server>
   <Listener>
   <SSLEngine>on</SSLEngine>
   <className>org.apache.catalina.core.AprLifecycleListener</className>
   </Listener>
   ...

I need everything to be rolled back up but despite my best efforts this has eluded me so far.

도움이 되었습니까?

해결책

It's hard enough to use XML::Simple for input, but output is very near impossible. I use XML::LibXML.

use XML::LibXML qw( );

my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('server.xml');

for my $server ($doc->findnodes('/Server')) {
   $server->setAttribute(port => $server_port);

   for my $connector ($server->findnodes('Service/Connector[0]') {
      $connector->setAttribute(port => $http_port);
   }
}

$doc->toFile('server.xml');

다른 팁

Reading the documentation of XML::Simple on CPAN, it seems like the NoAttr => 1 option in XMLout method is causing attributes to be converted to nested elements.

To quote the relevant part,

NoAttr => 1 # in+out - handy

When used with XMLout(), the generated XML will contain no attributes. All hash key/values will be represented as nested elements instead.

I suggest you use XML::Twig like that:

use XML::Twig;

my $change_port = sub { $_->set_att( port => 1234 ) };

my $twig = XML::Twig->new(
    twig_handlers => {
        'Server[@port]' => $change_port,
        'Connector[@port]' => $change_port,
    },
);
$twig->parsefile( 'server.xml' );
$twig->print_to_file( 'server.xml' );
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top