昔の C# や VB.NET のプロジェクトが沢山あり、最新の .NET Framework にマイグレーションしたい時、プロジェクトファイルの PropertyGroup や ItemGroup の設定値を更新する移行用のスクリプト書きたくなりますよね。
で、こんな感じで普通に xpath を指定して要素を取得しようとしてもちゃんと取れません。
$proj = [xml]Get-Content Target.csproj
$nodes = $proj.SelectNodes("//ItemGroup/Reference[contains(./@Include , 'System')]")
foreach($node in $nodes) { Write-Host $node.Include }
xpath に MSBuild のスキーマ情報を埋め込む必要があります。XmlNamespaceManager を使って MSBuild の namespace オブジェクトを生成し、SelectNodes の第2引数に渡すようにします。そして xpath には追加した namespace の prefix を付けます。
$proj = [xml]Get-Content Target.csproj
$ns = New-Object Xml.XmlNamespaceManager $proj.NameTable
$ns.AddNamespace("msb", "http://schemas.microsoft.com/developer/msbuild/2003")
$nodes = $proj.SelectNodes("//msb:ItemGroup/msb:Reference[contains(./@Include , 'System')]", $ns)
foreach($node in $nodes) { Write-Host $node.Include }
出力結果
System
System.Core
System.Xml.Linq
System.Data.DataSetExtensions
System.Data
System.Deployment
System.Drawing
System.Net.Http
System.Windows.Forms
System.Xml
ちゃんと取れました。