我正在尝试使用脚本自动化安装过程。该过程的一部分是查找 XML 配置文件的某些部分(如下所示),并更改某些参数,false
反之亦然true
。
配置文件中的许多部分都有该<enabled>
标签(在本例中是该<ssh>
部分)。那么,我的问题是,如何搜索特定<enabled>
标签并修改它?
<ssh>
<enabled>true</enabled>
<ip>0.0.0.0</ip>
<port>2024</port>
</ssh>
答案1
您还没有真正给出足够大的 XML 示例,所以我猜测了一下。
我建议完成这项工作的工具是一个不错的 XML 解析器和 perl。
我强烈建议您不要使用:
因为两者都很脆弱——它们在受控环境下可以工作,但是你有一些令人讨厌的黑客代码,有一天可能会神秘地破坏。
相反 - 使用支持的解析器xpath
- 用 XML 术语来说 - 一种查找/选择所需内容并修改它的方法。
比如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。
所以你有诸如//
递归查找之类的结构。
或者//node[@name='test']
寻找:
<node name="test">content</node>
有一个方便的快速参考这提供了一种简单的方法来了解如何使用 xpath 导航 XML。
答案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>