У меня есть функция, которая возвращает хеш-таблицу с различными ключами, один из которых — XML. У меня также есть код, предназначенный для проверки этого XML перед его возвратом. Тем не менее, у меня есть то, что сначала казалось проблемами загрязнения конвейера, но я изолировал это от кода замены XML.
Итак, изначально я делал всю замену XML напрямую с ключом в хэше возврата, используя $result.xml
. Однако с тех пор я изменил код, чтобы использовать отдельную переменную:
$revisedXml = $result.xml
$oldnode = $revisedXml.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$supersedes']")
$newnode = $temp.xml.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$supersedes']")
$importNode = $revisedXml.ImportNode($newnode, $true)
$oldnode.ParentNode.AppendChild($importNode)
$oldnode.ParentNode.RemoveChild($oldnode)
Однако любая из этих двух последних строк приводит к взрыву хэша $return
. Это заставило меня подумать, что я помню что-то о том, что XML существует по ссылке, а не по значению, поэтому на самом деле я напрямую обращаюсь к XML, просто через новый указатель, и то, что я меняю, каким-то образом взрывает всю переменную хеш-таблицы, которая также ссылается на XML. Это звучит правильно, или я уже иду по неверному пути?
Также и, возможно, связанные. Что я в конечном итоге хочу сделать, так это найти конкретный узел в $result.xml
и в другом $temp.xml
(загруженном из разных файлов) и, если он будет найден, заменить узел в $result
на узел из $temp
. Я пытался использовать ReplaceChild()
, но это, похоже, не работает, возможно, проблема с PowerShell 2.0.
Итак, с этими двумя битами данных есть ли лучший способ пересмотреть XML и есть ли способ заставить его работать с функцией, которая правильно передает XML по значению? FWIW, я рефакторинг, чтобы избежать глобальной переменной XML, которую я успешно использовал. Обычно я не люблю глобальные переменные, но, возможно, это тот случай, когда мне просто нужно их использовать?
EDIT: Итак, пытаемся изолировать проблему и сталкиваемся с новыми проблемами. Здесь я пытаюсь создать две XML-переменные в функции, заменить узел из одной переменной узлом из другой и передать его обратно из функции, затем написать в консоль, чтобы убедиться, что результат правильный (разница в том, что SilentModeID должен быть 9). Проблема в том, что две строки здесь не работают. Пробовал и с одинарными кавычками, но все равно выдает ошибки. Не совсем яблоки к яблокам, так как в моем реальном коде я не использую здесь строки, я читаю XML из файлов, но для целей обсуждения это казалось лучшим способом. Итак, первый новый вопрос, что, черт возьми, я делаю не так со строками здесь? Как только это заработает, мы сможем увидеть, нарушается ли передача XML обратно таким же образом.
function Write-PxXmlToConsole ($xml) {
$stringWriter = New-Object System.IO.StringWriter
$xmlWriter = New-Object System.Xml.XmlTextWriter $stringWriter
$xmlWriter.Formatting = "indented"
$xml.WriteTo($xmlWriter)
$xmlWriter.Flush()
$stringWriter.Flush()
Write-Host $stringWriter.ToString()
}
function Import-PxXml {
$result = @{
success = $true
xml = $null
log = $null
}
[xml]$assets = @"
<?xml version="1.0"?>
<Definitions>
<InstallTypes>
<InstallType id="deployment">
<SilentModeID>1</SilentModeID>
</InstallTypes>
</InstallType>
</Definitions>
"@
[xml]$newAssets = @"
<?xml version="1.0"?>
<Definitions>
<InstallTypes>
<InstallType id="deployment">
<SilentModeID>9</SilentModeID>
</InstallType>
</InstallTypes>
</Definitions>
"@
$nodeName = 'deployment'
$oldnode = $assets.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$nodeName']")
$newnode = $newAssets.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$nodeName']")
$importNode = $assets.ImportNode($newnode, $true)
$oldnode.ParentNode.AppendChild($importNode)
$oldnode.ParentNode.RemoveChild($oldnode)
$result.xml = $assets
$result.log = 'Crossed Fingers'
return $result
}
$test = Import-PxXml
Write-PxXmlToConsole $test.xml