我正在编写一个PowerShell脚本来操作一些Windows Installer XML(WiX).我正在使用.NET 3.5中的新XML API来实现这一点,因为我发现它比DOM更容易使用API.以下脚本片段断然拒绝工作:
[System.Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null # Basic idea: Iterate through en.wxl's l10ns, get string for each l10n, search all wxs files for that value. pushd "C:\temp\installer_l10n" $wxlFileName = "${pwd}\en.wxl" $wxl = [System.Xml.Linq.XDocument]::Load($wxlFileName) $strings = $wxl.Descendants("String") $strings $strings | foreach { $_ } popd
该脚本应在单独的行上输出每个
XML文档是标准的WiX本地化文件:
Advertising published resource Allocating registry space ...
$ strings不是$ null(我已经明确地测试了它),如果我写了host-wxl,我可以看到文件已被加载.将$字符串管理到Get-Member会返回一个错误,指出"没有为get-member指定任何对象",write-host $字符串不执行任何操作.我也尝试过$ wxl.Descendants("WixLocalization"),结果相同.像$ wxl.Root和$ wxl.Nodes这样的东西按预期工作.使用PowerShell ISE进行调试,我看到$ strings已设置为IEnumerator,而不是预期的IEnumerable
奇怪的是,相同的技术在以前的脚本中起作用.完全相同的代码,但具有不同的变量名和字符串文字.刚刚尝试调试该脚本(以验证行为),它似乎现在也显示相同的行为.
这个问题引起了我的兴趣,所以我做了一些搜索.经过PowerShell中的大量搜索和搜索网络后,我找到了解决方案.
感谢杰米汤姆森的实际代码. http://dougfinke.com/blog/index.php/2007/08/07/using-xmllinq-in-powershell/
缺少的部分是处理XML文件中的命名空间.以下代码应该适合您:
[System.Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null # Basic idea: Iterate through en.wxl's l10ns, get string for each l10n, search all wxs files for that value. $wxlFileName = "${pwd}\en.wxl" $wxl = [System.Xml.Linq.XDocument]::Load($wxlFileName) $ns = [System.Xml.Linq.XNamespace]”http://schemas.microsoft.com/wix/2006/localization” $strings = $wxl.Descendants($ns + "String") foreach ($string in $strings) { $string }