更改XML文档中的字段

时间:2016-07-28 20:57:00

标签: xml perl debian

我有一个具有以下结构的XML文件:

<user-mapping>
  <authorize username="user2" password="asdasdsss" >
    <connection name="U2 - Windows 7 ">
      <protocol>rdp</protocol>
      <param name="hostname">192.168.203.2</param>
      <param name="port">21122</param>
      <param name="password">asdasdsss</param>
      <param name="username">user</param>
    </connection>
    <connection name="U2 - Windows XP SP3 ">
      <protocol>rdp</protocol>
      <param name="hostname">192.168.203.2</param>
      <param name="port">21120</param>
      <param name="password">asdasdsss</param>
      <param name="username">user</param>
    </connection>
  </authorize>
</user-mapping>

此文件包含大约20个用户(authorize元素),每个用户有大约15个计算机连接。

我创建了一个Perl程序来仅更改密码字段,但它基于计算行和字符,直到找到该字段。如果我添加其他param元素,则必须修改脚本。

我希望有一种动态的doit方式,以便Perl可以选择正确的用户节点并更改所有相关计算机中的密码字段。我尝试了很多方法,但我无法让它发挥作用。

应为用户和所有计算机更改密码。它们都将被更改为相同的密码

我现在使用的代码:

open( FILL, "< /etc/user-mapping.xml" );

@strings = <FILL>;
$i = 0;

foreach $line (@strings) {
    print $i;
    print $line;
    $i++;
}

print "Number: ";
print $set_id;

$set_id = $set_id - 2;
$set_id = $set_id * 102;

print "Line: ";
print $set_id;

substr( @strings[ 1 + $set_id ],  43, 9 ) = "$password";
substr( @strings[ 6 + $set_id ],  39, 9 ) = "$password";
substr( @strings[ 13 + $set_id ], 39, 9 ) = "$password";

foreach $line ( @strings ) {
    print $i;
    print $line;
    $i++;
}

open( FH, "> /etc/user-mapping.xml" );
foreach $line (@strings) {
    print( FH $line );
}

close(FH);

close(FILL);

2 个答案:

答案 0 :(得分:3)

我希望您明白将密码保存为纯文本是一个非常糟糕的主意吗?

您必须使用正确的XML解析器,我建议您使用XML::Twig,因为它比某些替代方案更友好

这是一个按照你的要求做的程序。它会将密码更改为abc123。如您所见,它甚至比原始程序还要短

它使用XPath表达式查找文档中的所有/user-mapping/authorize元素,并将其密码属性更改为新密码。然后,它会查找每个connection/param元素中具有authorize属性的每个name="password"元素,并更改其中的文本值

use strict;
use warnings 'all';

use XML::Twig;

use constant XML_FILE     => 'user-mapping.xml';
use constant NEW_PASSWORD => 'abc123';
use constant USER_NAME    => 'user2';

my $twig = XML::Twig->new;
$twig->parsefile(XML_FILE);

for my $auth ( $twig->findnodes('/user-mapping/authorize') ) {

    next unless $auth->att('username') eq USER_NAME;

    $auth->set_att(password => NEW_PASSWORD);

    for my $pass ( $auth->findnodes('connection/param[@name="password"]') ) {

        $pass->set_text(NEW_PASSWORD);

    }    
}

$twig->set_pretty_print('indented');
$twig->print;

输出

<user-mapping>
  <authorize password="abc123" username="user2">
    <connection name="U2 - Windows 7 ">
      <protocol>rdp</protocol>
      <param name="hostname">192.168.203.2</param>
      <param name="port">21122</param>
      <param name="password">abc123</param>
      <param name="username">user</param>
    </connection>
    <connection name="U2 - Windows XP SP3 ">
      <protocol>rdp</protocol>
      <param name="hostname">192.168.203.2</param>
      <param name="port">21120</param>
      <param name="password">abc123</param>
      <param name="username">user</param>
    </connection>
  </authorize>
</user-mapping>

答案 1 :(得分:1)

使用真正的XML解析器。例如,使用XMLStarlet,这将非常简单:

xmlstarlet ed \
  -u '//authorize/@password' -v "new-password" \
  -u '//connection/param[@name="password"]' -v "new-password"