2016-03-20 2 views
0

Ich habe eine Funktion, die eine Hash-Tabelle mit einer Vielzahl von Schlüsseln zurückgibt, von denen einer XML ist. Ich habe auch Code, der dieses XML revidieren soll, bevor es es zurückgibt. Ich habe jedoch zunächst Probleme mit Pipeline-Verschmutzungen, aber ich habe es auf den XML-Ersatzcode beschränkt.XML-Funktion nach Wertproblem?

Also habe ich zunächst alle meine XML-Ersatz direkt mit dem Schlüssel in der Rückkehr Hash unter Verwendung $result.xml. Allerdings habe ich da den Code geändert, um eine separate Variable wie folgt zu verwenden:

$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) 

jedoch eine der beiden letzten beiden Zeilen ist, was die $return Hash bewirkt die Luft zu sprengen. Was mich denken lässt, dass ich denke, dass ich mich daran erinnere, dass XML nicht wertmäßig Referenz ist, sondern dass ich direkt auf das XML zugreife, nur über einen neuen Zeiger, und was ich verändere, sprengt irgendwie die ganze Hashtabellenvariable verweist auch auf das XML. Klingt das richtig, oder gehe ich schon einen falschen Weg?

Auch und vielleicht verwandt. Was ich letztendlich zu suchen suche ist nach einem bestimmten Knoten in $result.xml und in einem anderen $temp.xml (geladen von verschiedenen Dateien) und wenn gefunden, ersetzen Sie den in $result durch den von $temp. Ich habe versucht mit ReplaceChild(), aber das scheint nicht zu funktionieren, vielleicht ein PowerShell 2.0-Problem.

Also, gibt es mit diesen zwei Datenbits eine bessere Möglichkeit, das XML zu überarbeiten, und gibt es eine Möglichkeit, es mit einer Funktion arbeiten zu lassen, die den XML-Wert korrekt übergibt? FWIW, ich refactoring, um die globale XML-Variable zu vermeiden, die ich erfolgreich verwendet habe. Ich mag generell keine globalen Variablen, aber vielleicht ist das eine Situation, in der ich sie nur benutzen muss?

EDIT: Also, versuchen, das Problem zu isolieren und in neue Probleme zu laufen. Hier versuche ich zwei XML-Variablen in der Funktion zu erstellen, ersetze einen Knoten von einer Variablen mit dem Knoten von einer anderen und gebe ihn wieder aus der Funktion, schreibe dann in die Konsole, um zu verifizieren, dass das Ergebnis korrekt ist (der Unterschied ist SilentModeID) 9). Problem ist, dass die beiden Strings hier nicht funktionieren. Auch mit einfachen Anführungszeichen versucht, aber immer noch Fehler geworfen. Nicht wirklich Äpfel zu Äpfeln wie in meinem echten Code verwende ich nicht hier Strings, ich lese das XML aus Dateien, aber für die Zwecke der Diskussion schien es der bessere Weg zu gehen. Also, erste neue Frage, was zum Teufel mache ich falsch mit den hier Strings? Sobald das funktioniert, können wir sehen, ob das Zurückgehen des XML-Codes auf die gleiche Weise funktioniert.

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

„eine der beiden letzten beiden Zeilen ist, was den $ return Hash bewirkt die Luft zu sprengen“ In welcher Weise? –

+0

Es gibt das Aussehen eines beschädigten Pipeline-Problems. Wenn ich am Ende der Funktion durch $ return iteriere, sieht es "richtig" aus, aber wenn ich durch die Variable, die die Funktion empfängt, iteriere, erhält ich einen einzelnen Schlüssel ohne Namen und ohne Wert, aber mit einem .count von 3 Schlüsseln, nicht die vier Schlüssel, die im $ return-Hash in der Funktion sind. Entferne diese zwei Zeilen in der Funktion und alles funktioniert im aufrufenden Code. Aber natürlich wird das XML nicht geändert, daher ist es kein nützlicher Code, nur "funktionierender" Code. – Gordon

+1

Es gibt eine Menge anderen Code, also versuche ich, das Problem zu isolieren, um ein nützliches Beispiel ohne Hunderte von überflüssigen Zeilen zu schreiben. Aber das allein braucht eine Menge Zeit. – Gordon

Antwort

0

Die RemoveChild() und AppendChild() Methode gibt den untergeordneten Knoten in Frage, die Ausgabe zu verschmutzen.

die Ausgabe unterdrücken, und Sie werden in Ordnung sein:

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

Oh, huzzah! Verschmutzte Pipeline doch! Manchmal wünschte ich mir wirklich, es gäbe eine Möglichkeit, das Verhalten der Pipeline zu ignorieren und sich dann bei Bedarf wieder einzuschalten. In der Zwischenzeit, danke für die Weiterleitung! ;) – Gordon

+0

Ja, ich sehne mich auch nach einem strikten 'return' hin und wieder, aber du kannst nicht alles haben :) –

+0

True Dat. Und wirklich das Problem war ich vergaß Erste Regel von PowerShell: Es ist wahrscheinlich Pipeline-Verschmutzung Ab jetzt, wenn ich ein Problem habe und ich kann es zu einer Linie zu isolieren, meine erste Fehlersuche Schritt ist ein> $ null am Ende zu werfen und sehen was passiert. – Gordon

Verwandte Themen