2009-02-06 44 views
1

我正在編寫一個PowerShell腳本來操縱一些Windows安裝程序XML(WiX)。我在.NET 3.5中使用新的XML API來實現這一點,因爲我發現它比DOM更易於使用。下面的腳本片段斷然拒絕工作:爲什麼XDocument.Descendants()在PowerShell ISE中返回IEnumerator?

[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> 

$字符串不是$空(I」我已經明確地測試過了),如果我編寫主機$ wxl,我可以看到文檔已經加載。將$字符串傳送到Get-Member中會返回一個錯誤,指出「沒有對象被指定爲get-member」,write-host $字符串什麼也不做。我也嘗試了$ wxl.Descendants(「WixLocalization」),結果相同。像$ wxl.Root和$ wxl.Nodes這樣的東西按預期工作。使用PowerShell ISE調試,我發現$字符串已被設置爲IEnumerator,而不是預期的IEnumerable <XElement>。用一個MoveNext測試IEnumerator,然後用Current表示「Current =」,大概是$ null。

奇怪的是,相同的技術在以前的腳本中起作用。完全相同的代碼,但具有不同的變量名稱和字符串文字。並且剛剛嘗試調試該腳本(以驗證行爲),似乎它現在也顯示相同的行爲。

回答

5

這個問題引起了我的興趣,所以我做了一些搜索。在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 
} 
1

我知道你說過你最好不要使用DOM,但是有沒有什麼理由不適合你?

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

此輸出:

PS> $ test.WixLocalization.String

標識#text
- -----
0廣告出版資源
1分配註冊表空間

Foreach'ing在那應該不會太困難 在那時候。

+0

感謝您的回覆。由於這是工作中的問題,我將在週一回到辦公室時嘗試一下。 – alastairs 2009-02-07 09:32:07

+0

雖然我接受了其他答案,但它確實有效,因爲它使用了我已有的LINQ代碼。 – alastairs 2009-02-09 10:19:09