Я использую XML :: LibXML (2.0018; perl 5.16.3) У меня есть хеш, содержащий серию атрибутов, которые затем применяются к документу XML с использованием setAttribute()
. Этот материал предназначен для обновления файла tomcat server.xml, который необходимо изменить для работы с внешним интерфейсом apache httpd и который выполняется сценариями непрерывного развертывания.
Добавление основных атрибутов работает нормально:
use XML::LibXML qw ();
...
my %tmphash = ( port => "8581", address => "127.0.0.1", ... );
...
Тогда в некотором методе, который принимает ссылку на хеш:
foreach my $key (keys %$hashConnRef) {
$connector->setAttribute("$key" => $hasConnRef->{$key});
}
Все хорошо, до сих пор, где мне нужно добавить атрибут, который нуждается в литерале &
в выводе, чтобы tomcat правильно его подобрал.
Атрибут, который будет помещен в файл server.xml в файле, должен выглядеть следующим образом ( желаемый результат ):
relaxedQueryChars="[]|{}^\`"<>"
Однако, вызов setAttribute()
удобно преобразует «&» в «&», что приводит к ( токовому выходу ):
relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;"
Я пытался экранировать (и дважды экранировать) запись в хэше, например:
relaxedQueryChars => "[]|{}^\\\`\"\<\>"
К сожалению, в первом случае он просто ставит &#x5c;&#x60
, а во втором он добавляет \
перед &
.
Как определить строку в хэше, чтобы она обрабатывалась через setAttribute
и правильно выдавала \
?
По запросу, вот полный пример:
/ tmp / min.xml (по сути, все из разорванного tomcat conf / server.xml):
<?xml version="1.0" encoding="utf-8"?>
<Server port="8385" shutdown="SHUTDOWN">
<Service name="Catalina">
</Service>
</Server>
И минимальный пример программы:
#!/usr/bin/perl -w
use strict;
use warnings;
use XML::LibXML qw ( );
my %tmphash = (
port => "8381",
address => "127.0.0.1",
relaxedQueryChars => "[]|{}^\\\`\"\<\>"
);
sub edit_server_xml {
my ($serverFile, $hashConnRef) = @_;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($serverFile);
for my $server ($doc->findnodes("/Server")) {
# delete all of the defined connectors
for my $service ($server->findnodes("Service")) {
for my $connector ($service->findnodes("Connector")) {
$service->removeChild($connector);
}
}
my $connector = $doc->createElement("Connector");
for my $service ($server->findnodes("Service")) {
foreach my $key (keys %$hashConnRef) {
$connector->setAttribute("$key" => $hashConnRef->{$key});
}
$service->appendChild($connector);
$service->appendTextNode("\n");
}
$doc->toFile($serverFile);
}
}
edit_server_xml("/tmp/min.xml", \%tmphash);
Результирующая строка, которая неверна:
<Connector address="127.0.0.1" relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;" port="8381"/>