Почему XDocument.Descendants () возвращает IEnumerator в PowerShell ISE? - PullRequest
1 голос
/ 06 февраля 2009

Я пишу скрипт PowerShell для манипулирования некоторыми XML-файлами установщика Windows (WiX). Для этого я использую новые API-интерфейсы XML в .NET 3.5, так как считаю, что с ним проще работать, чем с 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

Сценарий должен выводить каждый тег в отдельной строке. Я собираюсь заставить его сделать что-то более интересное, как только эта ошибка будет решена; -)

Документ 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 не был указан объект», а запись «host-host $ strings» ничего не делает. Я также пробовал $ wxl.Descendants ("WixLocalization") с теми же результатами. Такие вещи, как $ wxl.Root и $ wxl.Node работают как положено. Отлаживая с помощью PowerShell ISE, я вижу, что для $ strings установлено IEnumerator, а не ожидаемый IEnumerable . Тестирование IEnumerator с одним MoveNext, а затем с Current указывает, что «Current =», предположительно $ null.

Странная вещь в том, что та же самая техника работала в предыдущем сценарии. Точно такой же код, но с разными именами переменных и строковыми литералами. И только что попробовав отладку этого скрипта (чтобы проверить поведение), кажется, что теперь он также показывает то же самое поведение.

Ответы [ 2 ]

5 голосов
/ 09 февраля 2009

Эта проблема заинтриговала меня, поэтому я немного покопался. После долгих раздумий в 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 голос
/ 06 февраля 2009

Я знаю, что вы сказали, что предпочитаете не работать с DOM, но есть ли причина, по которой это не работает для вас?

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

Это выводит:

PS> $ test.WixLocalization.String

Id # text
- -----
0 Рекламный опубликованный ресурс
1 Выделение места в реестре

Достижение этой цели не должно быть слишком сложным в этот момент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...