XML 个文件中的条件替换

Conditional replace in XML files

我正在使用 PowerShell 递归地替换 XML 文件中的文本。该脚本在替换方面工作正常。但是 XML 文件也有不应替换的文件路径。这是当前正在使用的脚本

if ( $content -match ' web site | web-site ' ) {
    $content -replace ' web site ',' New Site ' -replace ' web-site ',' New Site ' |
        Out-File $file.FullName -Encoding utf8

例如,如果 XML 文件有

<title>web site</title>
<subtitle>web-site</subtitle>
<path>c:/web site/website.xml</path>

预期的输出应该如下所示。应忽略文件路径中的匹配文本。如果字符串介于 /web site//web-site.xml 之间,我如何添加忽略字符串的条件?

<title>New Site</title>
<subtitle>New Site</subtitle>
<path>c:/web site/website.xml</path>

这是一个快速修复,但请注意更强大的解决方案将使用 PowerShell 的XML 解析功能:请参阅:

注:
- 这个答案假定感兴趣的字符串不与 XML 文档的语法元素冲突,例如元素名称和属性名称(恰好适用于 specific 字符串有问题),这说明了为什么使用真正的 XML 解析器是更好的选择。

$content = @'
<doc>
<title>web site</title>
<subtitle>web-site</subtitle>
<path>c:/web site/website.xml</path>
</doc>
'@

$modifiedContent = $content -replace '(^|[^/])web[ -]site([^/]|$)', 'New Site'
# Replace 'web site' and 'web-site' if not preceded or followed by a '/'.
# Note: `web[ -]site` is the equivalent of `web site|web-site`

if ($modifiedContent -cne $content) { # If contents have changed, save.
  Out-File -InputObject $modifiedContent $file.FullName -Encoding utf8
}

将 XML 处理为 XML 通常效率更高且更不容易出错。 Select您要更新的节点,然后将修改后的数据保存回文件。

$filename = 'C:\path\to\your.xml'

[xml]$xml = Get-Content $filename
$xml.SelectNodes('//*[self::title or self::subtitle]') |
    Where-Object { $_.'#text' -match 'web.site' } |
    ForEach-Object { $_.'#text' = 'New Site' }
$xml.Save($filename)

如果您需要修改节点文本的子字符串,您可以这样做:

$filename = 'C:\path\to\your.xml'

[xml]$xml = Get-Content $filename
$xml.SelectNodes('//*[self::title or self::subtitle]') |
    Where-Object { $_.'#text' -match 'web.site' } |
    ForEach-Object { $_.'#text' = $_.'#text' -replace 'web.site', 'New Site' }
$xml.Save($filename)