2016-07-22 16 views
1

XMLファイル内のテキストをPowerShellを使って再帰的に置き換えています。スクリプトは正常に動作しています。ただし、XMLファイルにはファイルパスがあり、置き換えてはいけません。 XMLファイルはXMLファイルの条件付き置換

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

を持っている場合、これは現在、例えば

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

を使用しているスクリプトが期待される出力は以下のようになるはずです。ファイルパス内の一致するテキストは無視する必要があります。 /web site/または/web-site.xmlの間に文字列を無視する条件を追加するにはどうすればよいですか?ここで

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

答えて

0

クイックフィックスだが、より堅牢なソリューションは、PowerShellののXML解析機能を使用することに注意してください:

注:
- この答えはの文字列と仮定しAnsgar Wiecher's helpful answerを参照してください関心は、要素名や属性名(特定の文字列ではうまくいく)のようなXML文書の構文要素と矛盾しません。実際のXMLパーサーが良い選択です。

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

$modifiedContent = $content -replace '(^|[^/])web[ -]site([^/]|$)', '$1New Site$2' 
# 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 
} 
+0

@Ansgar、それはあまりにも似たテキストの前後にスペースを持つことになります発生がありますmklement '新しいウェブサイト' thats/regexで/ text /を無視するためのクイックフィックスがあるかどうかを知りたかった理由私はこのためにquickfix foxを持っていますか、XMLの解析でこれを処理するためのリードを教えてください。 – user2628187

+0

@ user2628187:私の更新を見てください。 Ansgarの答えは特に 'title'と' subtitle'要素のみを対象としていますので、明示的に要素名のリストを使用しない限り、そのまま動作すると期待します。 – mklement0

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

うまくやった。私はOPのコードに一層よく一致させるために '-match 'web [ - ] site''を使うことを勧めます。 'self ::'を使っている特別な理由はありますか?それなしでうまくいくと思われる。 – mklement0

+1

「自己」軸もなくても動作することは知らなかった。 –

+0

はい、しかし、このオプションは使用できないようにproblenはファイルパスが多くの異なるxmlタグに来ることができます。前と最後のテキストを正規表現の形で指定することができますか?/ web site/ – user2628187