首页 > 解决方案 > 使用 PowerShell 从 XML 更新字符串

问题描述

我正在从一些 XML 数据中检索文本字符串,然后尝试用其他内容替换该字符串。我正在使用的代码是:

$newstring = "mystring"
$bar = Get-Gpo -Name "My GPO"
$gpoid = $bar.Id.ToString()
$drivesxml = New-Object XML
$drivesxml.Load("\\mydomain.co.uk\sysvol\mydomain.co.uk\Policies\{gpoid}\User\Preferences\Drives\drives.xml")
$oldpath = $drivesxml.Drives.Drive.Properties.Path[0]
$oldlabel = $drivesxml.Drives.Drive.Properties.Label[0]
#1
[string]$newtemppath = $oldpath -replace "Oldstring$", "$newstring"
[string]$newtemplabel = $oldlabel -replace "^Oldstring", "$newstring"
#2
$drivesxml.Drives.Drive.Properties.Path[0] = $newtemppath
$drivesxml.Drives.Drive.Properties.Label[0] = $newtemplabel
#3
$drivesxml.Save("\\mydomain.co.uk\sysvol\mydomain.co.uk\Policies\{gpoid}\User\Preferences\Drives\drives.xml")

它很好地从 sysvol 中检索 XML,如果我查询$oldpath并且$oldlabel它们包含来自 XML 的预期文本,则在第 1 点。

在#2,如果我查询$newtemppath并且$newtemplabel字符串按预期返回并修改了文本,因此“Oldstring”的实例已被“mystring”替换。

在#3,如果我查询$drivesxml.Drives.Drive.Properties.Path[0]并且$drivesxml.Drives.Drive.Properties.Label[0]我希望它们返回与$newtemppathand$newtemplabel变量相同的内容,但它们会继续返回其原始值。

如果我再次查询,保存 XML 后,内容没有改变。

谁能看到我在 #2 和 #3 之间的分配可能做错了什么?

标签: xmlpowershell

解决方案


Powershell 支持用于导航 XML 文件的“点路径”语法,这对于从 XML 文件读取数据非常方便——大概是为了方便使用 XML 输入或使用 XML 配置文件。

该语法的缺点是它会尽可能地尝试返回字符串和数组。在您的情况下,$drivesxml.Drives.Drive.Properties.Path[0]是一个字符串,而不是 XML 节点,因此您分配给该值的任何内容都将丢失。

诀窍是保留 XML 节点。实现这一点的最简单方法是使用 XPath 进行导航(无论如何它比点路径语法更强大):

$path = $drivesxml.SelectSingleNode('/Drives/Drive/Properties/Path')
$path.InnerText = $path.InnerText -replace "Oldstring$",$newstring

# ...

$drivesxml.Save($xmlPath)

您还可以使用.SelectNodesforeach循环来进行多项更改。


在不相关的说明中,Powershell 将在双引号字符串中进行变量插值。这可能与正则表达式发生冲突,其中$有其自身的含义。在上面的例子中没有歧义,但最好养成使用单引号字符串作为正则表达式的习惯:

$path.InnerText = $path.InnerText -replace 'Oldstring$',$newstring

关于 XML 命名空间的说明:如果您的 XML 文件使用命名空间xmlns由)?


推荐阅读