更改XML文档中的字段

更改XML文档中的字段,xml,perl,debian,Xml,Perl,Debian,我有一个具有以下结构的XML文件: rdp 192.168.203.2 21122 asdasdsss 使用者 rdp 192.168.203.2 21120 asdasdsss 使用者 该文件大约有20个用户授权元素,每个用户大约有15个机器连接 我创建了一个Perl程序,只更改密码字段,但它基于计算行数和字符数,直到找到该字段为止。如果我添加了额外的param元素,那么必须修改脚本 我希望有一种动态的方式来执行它,这样Perl就可以选择正确的用户节点并更改所有相关机器中的密码字段。我尝试了很

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

rdp 192.168.203.2 21122 asdasdsss 使用者 rdp 192.168.203.2 21120 asdasdsss 使用者 该文件大约有20个用户授权元素,每个用户大约有15个机器连接

我创建了一个Perl程序,只更改密码字段,但它基于计算行数和字符数,直到找到该字段为止。如果我添加了额外的param元素,那么必须修改脚本

我希望有一种动态的方式来执行它,这样Perl就可以选择正确的用户节点并更改所有相关机器中的密码字段。我尝试了很多方法,但都没有成功

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

我现在使用的代码:

打开FILL,/etc/user-mapping.xml; foreach$line@strings{ 打印FH$行; } 接近fh; 封闭填充;
使用真正的XML解析器。例如,使用XMLStarlet,这将非常简单:

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

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

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

我希望你明白,将密码保持为纯文本是一个非常糟糕的主意

您必须使用适当的XML解析器,我建议您使用它,因为它比其他方法更友好一些

这里有一个程序可以按你的要求执行。它会在整个过程中将密码更改为abc123。正如你所看到的,它甚至比你原来的程序还要短

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

严格使用; 使用“全部”警告; 使用XML::Twig; 使用常量XML_FILE=>'user mapping.XML'; 使用常量NEW_PASSWORD=>“abc123”; 使用常量USER_NAME=>user2; my$twig=XML::twig->new; $twig->parsefileXML\u文件; 对于我的$auth$twig->findnodes'/user mapping/authorize'{ 下一步除非$auth->att'username'eq USER\u NAME; $auth->set_attpassword=>新建_密码; 对于我的$pass$auth->findnodes'connection/param[@name=password]'{ $pass->set_text新建_密码; } } $twig->set_pretty_打印“缩进”; $twig->print; 输出 rdp 192.168.203.2 21122 abc123 使用者 rdp 192.168.203.2 21120 abc123 使用者
我希望你明白,将密码保持为纯文本是一个非常糟糕的主意

您必须使用适当的XML解析器,我建议您使用它,因为它比其他方法更友好一些

这里有一个程序可以按你的要求执行。它会在整个过程中将密码更改为abc123。正如你所看到的,它甚至比你原来的程序还要短

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

严格使用; 使用“全部”警告; 使用XML::Twig; 使用常量XML_FILE=>'user mapping.XML'; 使用常量NEW_PASSWORD=>“abc123”; 使用常量USER_NAME=>user2; my$twig=XML::twig->new; $twig->parsefileXML\u文件; 对于我的$auth$twig->findnodes'/user mapping/authorize'{ 下一步除非$auth->att'username'eq USER\u NAME; $auth->set_attpassword=>新建_密码; 对于我的$pass$auth->findnodes'connection/param[@name=password]'{ $pass->set_text新建_密码; } } $twig->set_pretty_打印“缩进”; $twig->print; 输出 rdp 192.168.203.2 21122 abc123 使用者 rdp 192.168.203.2 21120 abc123 使用者
如果您试图修改XML数据,您应该使用XML解析器……实际上也有一些非常优秀的perl XML解析器。@CharlesDuffy:不幸的是,这些解析器甚至比优秀的更笨重,这是新手的雷区如果你试图修改XML数据,你应该使用XML解析器……实际上也有一些非常优秀的perl XML解析器。@CharlesDuffy:不幸的是,这些解析器比优秀的解析器更笨重,这是新手的雷区我正在为我的a开发xsh扩展
nswer,但是没有必要这样做。@Borodin我已经测试了你的脚本,但我遇到了这样的问题:1-它将更改所有授权和所有计算机的密码,正如我所说,我有大约20个用户具有相同的ex。所以我如何选择授权,其中username=user3/user4等等,并仅更改此用户和相应计算机的密码。2-输出仅在终端窗口中,我希望脚本更改文件中的值,我尝试了这个方法,但它无法运行print{$XMLpath}$twig->sprint;3-密码位置已替换为用户名位置,感谢alot mate。@Ti2:1>>我已更改代码以仅更改用户的密码2>>您肯定知道可以将命令的输出重定向到您喜欢的任何文件吗?写一个修改源数据的程序是个坏主意,因为如果程序中有错误,源数据将被损坏3>>我不知道你的意思。我想我已经回答了你的问题。如果你不能进步,那么你应该提出一个新问题。@Borodin这是一个完美的人,非常感谢,这正是我想要的,我将按照你的建议添加MD5编码,并将输出重定向到新文件并创建检查完整性函数,这是唯一一个包含所有用户信息的XML文件。3> >我的意思是用户名值和密码值的位置在编辑后被交换{username 1st->password 2nd}它变成了{password 1st->username 2nd},但我认为这没有问题,我会看看服务器是否能够正确读取它,或者noI正在为我的答案使用xsh扩展,但是没有必要这样做。@Borodin我已经测试了你的脚本,但是我遇到了这样的问题:1-它将更改所有授权和所有机器的密码,正如我所说,我有大约20个用户具有相同的ex。所以我如何选择授权,其中username=user3/user4等等,并仅更改此用户和相应计算机的密码。2-输出仅在终端窗口中,我希望脚本更改文件中的值,我尝试了这个方法,但它无法运行print{$XMLpath}$twig->sprint;3-密码位置已替换为用户名位置,感谢alot mate。@Ti2:1>>我已更改代码以仅更改用户的密码2>>您肯定知道可以将命令的输出重定向到您喜欢的任何文件吗?写一个修改源数据的程序是个坏主意,因为如果程序中有错误,源数据将被损坏3>>我不知道你的意思。我想我已经回答了你的问题。如果你不能进步,那么你应该提出一个新问题。@Borodin这是一个完美的人,非常感谢,这正是我想要的,我将按照你的建议添加MD5编码,并将输出重定向到新文件并创建检查完整性函数,这是唯一一个包含所有用户信息的XML文件。3> >我的意思是用户名值和密码值的位置在编辑后被交换{username 1st->password 2nd}它变成了{password 1st->username 2nd},但我认为这没有问题,会看看服务器是否能够正确读取它,除了/user-mapping/authorize元素的属性。多亏了你的帖子,我才发现XMLStarlet可用于Windows,尽管我想我更喜欢一种既定的SAX方法。是的,除了/user-mapping/authorize元素的属性。多亏了你的帖子,我刚刚发现XMLStarlet可用于Windows,尽管我认为我更喜欢一种已建立的SAX方法。