Verständnisprobleme XML mit Powershell
Moin zusammen,
ich hoffe mir kann jemand auf die Sprünge helfen. Ich hatte bisher kaum was mit XML-Dateien zu tun, was das programmieren angeht. Wie ich den Dokus, die ich bisher versucht habe zu verstehen, anscheinend eine extreme Wissenslücke.
Es geht auf jeden Fall um folgendes: Ich habe hier eine XML-Datei vorliegen, in denen ich einen Wert austauschen muss. Dieses leider aber immer wieder - deswegen ist das Suchen und Ersetzen mit einem Editor keine Option.
Der Aufbau der XML sieht wie folgt aus:
<Haupt>...</Haupt> wiederholt sich 1000de male
Nun möchte ich bei den "Punkt"en, bei denen die "Eigenschaft" "Farbe" ist auf "Hauptfarbe" ändern.
Mein Ansatz sieht bisher so aus:
Wenn ich das soweit richtig verstanden habe, müsste $doc jetzt eine Art Array repräsentieren, in welchen nur noch die passenden Einträge sind.
Leider ist das nicht so - bzw. kann nicht so sein, weil ich, wenn ich ein
ausführe, ich alle Werte angezeigt bekomme - sprich ungefiltert.
Noch einmal zusammengefasst. Was ich erreichen will ist folgendes: XML laden, einen bestimmten Wert, der mehrfach vorkommen kann, auf einen anderen Wert ändern, und das ganze zurück in die Datei schreiben.
mein Gefühl sagt mir, dass das irgendwie mit foreach funktionieren müsste. Ich bekomme das Ganze aber irgendwie nicht zusammen.
Die Tutorials, die ich bisher gefunden habe, u.a. von @colinardo gehen leider immer davon aus, das sich jedes Element eindeutig referenzieren lässt (ID, Name oder ähnliches).
Vielleicht habe ich aber nur den Faden verloren.
Vielen Dank im voraus
Krämer
ich hoffe mir kann jemand auf die Sprünge helfen. Ich hatte bisher kaum was mit XML-Dateien zu tun, was das programmieren angeht. Wie ich den Dokus, die ich bisher versucht habe zu verstehen, anscheinend eine extreme Wissenslücke.
Es geht auf jeden Fall um folgendes: Ich habe hier eine XML-Datei vorliegen, in denen ich einen Wert austauschen muss. Dieses leider aber immer wieder - deswegen ist das Suchen und Ersetzen mit einem Editor keine Option.
Der Aufbau der XML sieht wie folgt aus:
<Stamm>
<Haupt>BezeichnungHaupt
<Unter>BezeichnungUnter
<Punkt>
<Eigenschaften>
<Eigenschaft>Farbe</Eigenschaft>
<Wert>Rot</Wert>
</Eigenschaften>
</Punkt>
</Unter>
</Haupt>
</Stamm>
<Haupt>...</Haupt> wiederholt sich 1000de male
Nun möchte ich bei den "Punkt"en, bei denen die "Eigenschaft" "Farbe" ist auf "Hauptfarbe" ändern.
Mein Ansatz sieht bisher so aus:
$MYXML=$TempPath+"MY.XML"
$doc=[XML] (Get-Content -path $MYXML)
$doc.SelectNodes("Eigenschaften[contains(Eigenschaft,'Farbe')]")
Leider ist das nicht so - bzw. kann nicht so sein, weil ich, wenn ich ein
$doc.GetElementsByTagName("Wert")
Noch einmal zusammengefasst. Was ich erreichen will ist folgendes: XML laden, einen bestimmten Wert, der mehrfach vorkommen kann, auf einen anderen Wert ändern, und das ganze zurück in die Datei schreiben.
mein Gefühl sagt mir, dass das irgendwie mit foreach funktionieren müsste. Ich bekomme das Ganze aber irgendwie nicht zusammen.
Die Tutorials, die ich bisher gefunden habe, u.a. von @colinardo gehen leider immer davon aus, das sich jedes Element eindeutig referenzieren lässt (ID, Name oder ähnliches).
Vielleicht habe ich aber nur den Faden verloren.
Vielen Dank im voraus
Krämer
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 314027
Url: https://administrator.de/forum/verstaendnisprobleme-xml-mit-powershell-314027.html
Ausgedruckt am: 21.12.2024 um 16:12 Uhr
14 Kommentare
Neuester Kommentar
Hallo Krämer,
du musst schon das Ergebnis der Funktion selectNodes() in eine Variable speichern . $doc verändert sich damit nicht!
Hier ein simples Beispiel (Der Einfachheit habe ich das XML hier ins Skript eingebaut):
Grüße Uwe
du musst schon das Ergebnis der Funktion selectNodes() in eine Variable speichern . $doc verändert sich damit nicht!
Hier ein simples Beispiel (Der Einfachheit habe ich das XML hier ins Skript eingebaut):
$xml = [xml]@"
<Stamm>
<Haupt>BezeichnungHaupt
<Unter>BezeichnungUnter
<Punkt>
<Eigenschaften>
<Eigenschaft>Farbe</Eigenschaft>
<Wert>Rot</Wert>
</Eigenschaften>
</Punkt>
</Unter>
</Haupt>
</Stamm>
"@
# Nodes selektieren
$nodes = $xml.SelectNodes("//Eigenschaften[contains(Eigenschaft,'Farbe')]")
# Eigenschaft der Nodes ändern
$nodes | %{$_.Wert = "Anderer Wert"}
# XML speichern
$xml.Save('D:\out.xml')
Zitat von @Kraemer:
Cool. Vielen Dank Uwe!
Verstehe ich das richtig, das hier nicht das "Ergebnis" nach $nodes "kopiert" wird, sondern $nodes "nur" ein Pointer auf die Ergebnismenge ist?
Ja. Wenn du hier Änderungen vornimmst sind diese auch im XML-Dokument wiederzufinden weil man hier das XML-Dokument und deren Nodes verändert.Cool. Vielen Dank Uwe!
Verstehe ich das richtig, das hier nicht das "Ergebnis" nach $nodes "kopiert" wird, sondern $nodes "nur" ein Pointer auf die Ergebnismenge ist?
$nodes | %{$_.Wert = "Anderer Wert"}
Dieses Pipe-Konstrukt verstehe ich noch nicht. Wenn ich das irgendwo nachlesen will - nach welchem Suchbegriff muss ich suchen?Mit dem $_ sprichst du das aktuelle Objekt und dessen Eigenschaften in der Schleife an.
Eine kurze Frage noch. Die Original-XML ist optisch eine schöne Datei (Einrückungen, Linebreaks etc). Leider verstümmelt die Powershell das beim .save. Dafür gibt es nicht zufällig auch eine Abhilfe?
Das kannst du mit einem XMLWriter machen:$xml = [xml]@"
<Stamm>
<Haupt>
<Unter>
<Punkt>
<Eigenschaften>
<Eigenschaft>Farbe</Eigenschaft>
<Wert>Rot</Wert>
</Eigenschaften>
<Eigenschaften>
<Eigenschaft>Farbe</Eigenschaft>
<Wert>Rot</Wert>
</Eigenschaften>
</Punkt>
</Unter>
</Haupt>
</Stamm>
"@
$nodes = $xml.SelectNodes("//Eigenschaften[contains(Eigenschaft,'Farbe')]")
$nodes | %{$_.Wert = "Anderer Wert"}
$xmlwritersettings = New-Object System.Xml.XmlWriterSettings
$xmlwritersettings.Indent = $true
$xmlwriter = [System.Xml.XmlWriter]::Create('D:\out.xml',$xmlwritersettings)
$xml.Save($xmlWriter)
$xmlwriter.Close()
Doch das funktioniert 100%, das liegt dann an deiner Quelldatei und wie dort die Inhalte gesetzt sind. Geht hier einwandfrei.
Das Problem bei deinem XML oben ist das dier:
Der verhindert das das gesamte Dokument vernünftig formatiert wird, -> Bezeichnung ohne Tag, das führt dazu.
Die zusätzlichen Attribute die du dem $xmlsettings Objekt hinzugefügt hast sind nicht nötig.
Das Problem bei deinem XML oben ist das dier:
<Haupt>BezeichnungHaupt
<Unter>BezeichnungUnter
Die zusätzlichen Attribute die du dem $xmlsettings Objekt hinzugefügt hast sind nicht nötig.
Zitat von @Kraemer:
Werde jetzt versuchen das wie folgendes Muster umzusetzen: <gangster name='George "Shotgun" Ziegler'>
Ein Attribut kannst du so erzeugen und an einen Knoten anhängen:Werde jetzt versuchen das wie folgendes Muster umzusetzen: <gangster name='George "Shotgun" Ziegler'>
# Attribut erstellen
$attr = $xml.CreateAttribute("name")
# Wert zuweisen
$arr.value = "George Shotgun Ziegler"
# Attribut einem Knoten zuweisen
$xml.Stamm.Haupt.Attributes.Append($attr)