Скрипт для изменения XML-файла конфигурации

Скрипт для изменения XML-файла конфигурации

Я пытаюсь автоматизировать процесс установки с помощью скрипта. Часть процесса заключается в поиске определенных разделов XML-файла конфигурации (см. ниже) и изменении определенных параметров с falseна trueили наоборот.

В файле конфигурации есть много разделов, которые имеют <enabled>тег (в данном случае это <ssh>раздел). Итак, мой вопрос в том, как мне найти конкретный <enabled>тег и изменить его?

<ssh>
  <enabled>true</enabled>
  <ip>0.0.0.0</ip>
  <port>2024</port>
</ssh>

решение1

Вы не привели достаточно большой пример XML, поэтому мне остается лишь немного догадываться.

Я бы предположил, что инструментом для этой работы будет приличный XML-парсер и Perl.

Я настоятельно рекомендую вам НЕ использовать:

Потому что оба варианта хрупкие — они работают в контролируемых условиях, но у вас есть хакерский, опасный код, который может по непонятной причине сломаться в один прекрасный день.

Вместо этого используйте синтаксический анализатор, который поддерживает xpathXML, что является способом поиска/выбора нужного вам контента и его изменения.

Что-то вроде этого XML::Twigимеет низкий порог входа. (XML::LibXML также является хорошей альтернативой, но гораздо более исчерпывающей).

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig; 

#parse the content - you probably want `parsefile` here instead. 
my $twig = XML::Twig -> new ( pretty_print => 'indented_a' ) -> parse ( \*DATA );

#select the node you want, alter it. 
$twig -> get_xpath('./ssh/enabled',0) -> set_text('false');

#print the output (to STDOUT) - you can print {$output_fh} $twig->sprint; instead
$twig -> print;


__DATA__
<xml>
  <www>
    <enabled>true</enabled>
    <ip>0.0.0.0</ip>
    <port>80</port>
  </www>
  <ssh>
    <enabled>true</enabled>
    <ip>0.0.0.0</ip>
    <port>2024</port>
  </ssh>
  <smtp>
    <enabled>true</enabled>
    <ip>0.0.0.0</ip>
    <port>25</port>
  </smtp>
</xml>

Примечание - get_xpathиспользует формат типа "структура каталогов". Он поддерживает абсолютные пути в XML, а также относительные пути. При выполнении вышеописанного способа он будет работать с первым элементом, соответствующим этому пути (XML допускает несколько).

Однако вы можете сделать это в цикле foreach:

foreach my $thing ( $twig -> get_xpath ('//enabled') ) {
   $thing -> set_text('false'); 
}

чтобы отключить все.

xpathдовольно гибкий - это способ указания пути, элемента и атрибутов иидеально подходитдля навигации по XML с использованием регулярных выражений.

Итак, у вас есть такие конструкции, как //for find recursive.

Или //node[@name='test']найти:

<node name="test">content</node>

Естьудобный краткий справочникЭто дает простой способ увидеть, как перемещаться по XML с помощью XPath.

решение2

Поскольку несколько узлов в вашем файле конфигурации имеют дочерние узлы с одинаковым именем, я бы рекомендовал писать ваш скрипт таким образом, чтобы он действительно понимал формат XML. Вот пример Perl для изменения двух ваших элементов конфигурации:

#!/usr/bin/perl

use strict;
use warnings;

use XML::Simple;

my $config = 'config.xml';
my $xml = XMLin($config, KeepRoot => 1, ForceArray => 1,);

$xml->{config}->[0]->{ssh}->[0]->{enabled} = 'false';
$xml->{config}->[0]->{web}->[0]->{ip} = '127.0.0.1';

XMLout($xml, KeepRoot => 1, NoAttr => 1, OutputFile => $config,);

Вот мой вклад config.xml:

<config>
  <ssh>
    <enabled>true</enabled>
    <ip>0.0.0.0</ip>
    <port>2024</port>
  </ssh>
  <web>
    <enabled>true</enabled>
    <ip>0.0.0.0</ip>
    <port>80</port>
  </web>
</config>

И вот что получилось:

<config>
  <ssh>
    <enabled>false</enabled>
    <ip>0.0.0.0</ip>
    <port>2024</port>
  </ssh>
  <web>
    <enabled>true</enabled>
    <ip>127.0.0.1</ip>
    <port>80</port>
  </web>
</config>

Связанный контент