2016-03-20 6 views
0

У меня есть функция, которая возвращает хеш-таблицу с множеством ключей, одним из которых является XML. У меня также есть код, предназначенный для пересмотра этого 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. Правильно ли это звучит, или я уже ошибаюсь?

Также, возможно, связанный. В конечном итоге я ищу поиск определенного узла в и в другом $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 
+1

«либо из этих двух последних строк является то, что вызывает $ возвращает хеш взрывать» В каком смысле? –

+0

Это приводит к возникновению проблемы с коррупцией. Если я перебираю через $ return в конце функции, он выглядит «правильно», но повторяя через переменную, которая получает функцию, я получаю то, что кажется единственным ключом, без имени и без значения, но с .count из 3 ключей, а не четырех ключей, которые находятся в хэш-функции $ return в функции. Удалите эти две строки в функции, и все работает в вызывающем коде. Но, конечно, XML не изменился, поэтому он не полезный код, просто «рабочий» код. – Gordon

+1

Есть куча другого кода, поэтому я пытаюсь изолировать проблему достаточно, чтобы опубликовать полезный пример без сотен посторонних строк. Но это само по себе занимает кучу времени. – Gordon

ответ

0

RemoveChild() и AppendChild() метод возвращает дочерний узел в вопросе, загрязняя свой выход.

Подавить вывод, и вы будете в порядке:

$null = $oldnode.ParentNode.AppendChild($importNode) 
$null = $oldnode.ParentNode.RemoveChild($oldnode) 
+0

О, хузза! Загрязненный трубопровод в конце концов! Иногда мне действительно хотелось бы, чтобы был способ отказаться от поведения в конвейере, а затем, если нужно, отбросьте назад. Тем временем, спасибо за перенаправление! ;) – Gordon

+0

Да, я слишком долго жаждет «возвращения», но у вас не может быть всего :) –

+0

True Dat. И действительно, проблема была в том, что я забыл Первое правило PowerShell: Вероятно, это загрязнение трубопровода С этого момента, если у меня есть проблема, и я могу выделить ее в строке, мой первый шаг по устранению неполадок - это выбросить> $ null на конец и посмотреть, что произойдет. – Gordon