XML文件中的条件替换

时间:2016-07-22 20:46:15

标签: powershell powershell-v2.0 powershell-v3.0

我正在使用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>

2 个答案:

答案 0 :(得分:4)

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

$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)

答案 1 :(得分:0)

以下是快速修复,但请注意更强大的解决方案将使用PowerShell的XML解析功能:请参阅Ansgar Wiecher's helpful answer

注意:
- 这个答案假设感兴趣的字符串不与XML文档的语法元素冲突,例如元素名称和属性名称(这恰好适用于所讨论的特定字符串),这说明了原因使用真正的XML解析器是更好的选择。

template<typename T, size_t S>
struct Vec;
template<typename T>
struct Vec<T, 1> {
  enum {count = 1};
  T x;
  T& operator[](size_t i) {
    assert(i == 0);
    return x;
  }
  const T& operator[](size_t i) const {
    assert(i == 0);
    return x;
  }
};
template<typename T>
struct Vec<T, 2> {
  enum { count = 2 };
  T x;
  T y;
  T& operator[](size_t i) {
    assert(0 <= i && i < count);
    return this->*(pointer(i));
  }
  const T& operator[](size_t i) const {
    assert(0 <= i && i < count);
    return this->*(pointer(i));
  }
  static T Vec::* pointer(size_t i) {
    static T Vec::* a[count] = { &Vec::x, &Vec::y };
    return a[i];
  }
};
template<typename T>
struct Vec<T, 3> {
  enum { count = 3 };
  T x;
  T y;
  T z;
  T& operator[](size_t i) {
    assert(0 <= i && i < count);
    return this->*(pointer(i));
  }
  const T& operator[](size_t i) const {
    assert(0 <= i && i < count);
    return this->*(pointer(i));
  }
  static T Vec::* pointer(size_t i) {
    static T Vec::* a[count] = { &Vec::x, &Vec::y, &Vec::z };
    return a[i];
  }
};

int main() {
  Vec<int, 2> v1{ 1, 2 };
  assert(v1[0] == v1.x);
  assert(v1[1] == v1.y);

  Vec<unsigned char, 3> v2{ 4, 5, 6 };
  assert(v2[0] == v2.x);
  assert(v2[1] == v2.y);
  assert(v2[2] == v2.z);
  return 0;
}