1

我正在编写一个 PowerShell 脚本来操作一些 Windows Installer XML (WiX)。我正在使用 .NET 3.5 中的新 XML API 来执行此操作,因为我发现它比 DOM 更易于使用。以下脚本片段断然拒绝工作:

[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

该脚本在单独的行上输出每个 <String> 标记。一旦这个错误被解决,我将让它做一些更有趣的事情;-)

XML 文档是一个标准的 WiX 本地化文件:

<?xml version="1.0" encoding="utf-8" ?>
<WixLocalization Culture="en-US" xmlns="http://schemas.microsoft.com/wix/2006/localization">
   <String Id="0">Advertising published resource</String>
   <String Id="1">Allocating registry space</String>
   ...
</WixLocalization>

$strings 不是 $null(我已经明确测试过),如果我写主机 $wxl,我可以看到文档已经加载。将 $strings 导入 Get-Member 会返回一个错误,指出“没有为 get-member 指定对象”并且 write-host $strings 什么也不做。我也试过 $wxl.Descendants("WixLocalization") 得到相同的结果。$wxl.Root 和 $wxl.Nodes 之类的东西按预期工作。使用 PowerShell ISE 进行调试,我看到 $strings 已设置为 IEnumerator,而不是预期的 IEnumerable<XElement>。使用单个 MoveNext 和 Current 测试 IEnumerator 指示“Current =”,大概是 $null。

奇怪的是,相同的技术在以前的脚本中也有效。完全相同的代码,但具有不同的变量名和字符串文字。并且刚刚尝试调试该脚本(以验证行为),它现在似乎也显示相同的行为。

4

2 回答 2

5

这个问题引起了我的兴趣,所以我做了一些搜索。在 PowerShell 中搞砸了很多东西并在网上搜索后,我找到了您的解决方案。

实际代码归功于 Jamie Thomson。 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
}
于 2009-02-09T07:06:05.277 回答
1

我知道你说过你不喜欢使用 DOM,但是有什么理由不适合你吗?

[xml]$test = gc .\test.wml                                                                                        
$test                                                                                                             
$test.WixLocalization                                                                                             
$test.WixLocalization.String

这输出:

PS> $test.WixLocalization.String

Id #text
-- -----
0 广告发布资源
1 分配注册表空间

在那一点上,解决这个问题应该不会太困难。

于 2009-02-06T18:52:07.857 回答