为什么 XDocument.Descendants() 在 PowerShell ISE 中返回 IEnumerator?
我正在编写一个 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 本地化文件:
<?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(我已经明确测试过它),如果我写- host $wxl,可以看到文档已经加载了。 通过管道将 $strings 传送到 Get-Member 会返回一个错误,指出“没有为 get-member 指定任何对象”,而 write-host $strings 不执行任何操作。 我也尝试过 $wxl.Descendants("WixLocalization") ,结果相同。 像 $wxl.Root 和 $wxl.Nodes 这样的东西按预期工作。 使用 PowerShell ISE 进行调试,我发现 $strings 已设置为 IEnumerator,而不是预期的 IEnumerable
奇怪的是,同样的技术在以前的脚本中也有效。 完全相同的代码,但具有不同的变量名称和字符串文字。 并且刚刚尝试调试该脚本(以验证行为),它现在似乎也显示相同的行为。
I'm writing a PowerShell script to manipulate some Windows Installer XML (WiX). I'm using the new XML APIs in .NET 3.5 to do this, as I find it an easier API to work with than the DOM. The following script fragment is flatly refusing to work:
[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
The script should output each <String> tag on a separate line. I'm going to get it to do something more interesting once this bug's been solved ;-)
The XML document is a standard WiX localisation file:
<?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 is not $null (I've explicitly tested it), and if I write-host $wxl, I can see that the document has been loaded. Piping $strings into Get-Member returns an error stating that "No object has been specified to get-member" and write-host $strings does nothing. I've also tried $wxl.Descendants("WixLocalization") with the same results. Things like $wxl.Root and $wxl.Nodes work as expected. Debugging with PowerShell ISE, I see that $strings has been set to IEnumerator, rather than the expected IEnumerable<XElement>. Testing the IEnumerator with a single MoveNext and then a Current indicates that "Current = ", presumably $null.
The weird thing is that the same technique worked in a previous script. The exact same code, but with different variable names and string literals. And having just tried debugging that script too (to verify the behaviour), it seems it's now also displaying the same behaviour.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这个问题引起了我的兴趣,所以我做了一些搜索。 在 PowerShell 中进行了大量的尝试并在网络上进行搜索之后,我找到了您的解决方案。
实际代码归功于 Jamie Thomson。
http://dougfinke.com/blog/ index.php/2007/08/07/using-xmllinq-in-powershell/
缺少的部分是处理 XML 文件中的命名空间。 这是应该适合您的代码:
This problem intrigued me, so I did some searching around. After a lot of messing around in PowerShell and searching the web I found your solution.
Credit goes to Jamie Thomson for the actual code.
http://dougfinke.com/blog/index.php/2007/08/07/using-xmllinq-in-powershell/
The missing piece is to handle the namespace in the XML file. Here is the code that should work for you:
我知道您说过您不喜欢使用 DOM,但是有什么理由说明这对您不起作用吗?
这输出:
PS> $test.WixLocalization.String
Id #text
-- -----
0 广告发布资源
1 分配注册表空间
此时进行查找应该不会太困难。
I know you said you prefered not to work with the DOM, but is there any reason why this doesn't work for you?
This outputs:
PS> $test.WixLocalization.String
Id #text
-- -----
0 Advertising published resource
1 Allocating registry space
Foreach'ing over that shouldn't be too difficult at that point.