atlas2
Goto Top

XML Datei auslesen und schreiben mit Powershell

Hallo zusammen,

ich muss mehrere XML Dateien bearbeiten . Normalerweise benutze ich, um einzelne Elemente in Dateien zu ändern und auszulesen, die cmd.exe. Bei Text Dateien funktioniert das auch immer sehr gut. Nun kommt es aber beim Zerlegen von XML Dateien immer wieder zu Problemen wie Sonderzeichen oder das Limit von Token. Deshalb möchte ich das zum Anlass nehmen, um mich in die Powershell einzuarbeiten. Leider habe ich da keine Erfahrung und hoffe, dass ich hier etwas Hilfe bekomme.
Die XML Dateien sehen etwa so aus.
<?xml version="1.0" encoding="utf-8" ?>  
<partsmanagemement count=“1“ ….>
	<part part_one=“Wert“ part_two=”Wert” usw…2000.Zeichen.>
	<…>
	<…>
	</part>
</partmanagement>
<partsmanagemement count=“1“ ….>
…

Innerhalb einer solchen Struktur benötige ich nur eine Zeile (<part part_one=“Wert). Hier benötige ich den Wert von „part_two“ und „part_sixty-five“ diese beiden Werte sollen durch einen Punkt getrennt, nach „part_two“ geschrieben werden und der Rest soll so erhalten bleiben. Bei der cmd.exe hätte ich zeilenweise die Datei ausgelesen, mit IF Else auf die Zeile gewartet, diese dann zerlegt und wieder zusammengesetzt. Nun die Frage, wie setze ich das aber nun mit der Powershell um? Die beiden benötigten Werte habe ich mir wie folgt mal „zusammengeschustert“.
$meinstring = Select-String -Path .\datei.xml -Pattern P_ARTICLE_PARTNR 
$teil1 = "$meinstring".Split('"') ; $teil1[5]   
$teil2 = "$meinstring".Split('"') ; $teil2[65]   
Leider weiß ich nun nicht weiter bzw. ob das so überhaupt der richtige Ansatz ist?!?
Die Werte stehen vor P_ARTICLE_MANUFACTURER="xxx" und P_ARTICLE_PARTNR="xxx"
Vielen Dank

Content-ID: 623872

Url: https://administrator.de/contentid/623872

Ausgedruckt am: 08.11.2024 um 14:11 Uhr

Printe
Lösung Printe 19.11.2020 aktualisiert um 13:51:31 Uhr
Goto Top
Kein Thema ... aber lass den "Shiet" mit dem Split face-wink Powerhell kann XML nativ parsen, in Objekte zerlegen und mittels XPath passende Knoten selektieren!
$file = 'D:\Datei.xml'  
$xml = [xml](gc $file)
$xml.SelectNodes("//partsmanagement/part[@part_two and @part_sixty-five]") | %{  
    $_.part_two = "$($_.part_two).$($_.'part_sixty-five')"  
}
$xml.Save($file)

btw. dein hier gepostetes XML ist übrigens nicht valide, es hat mehrere Root(DocumentElement)-Knoten und das kann eine XML nicht, eine XML kann nur ein einziges "DocumentElement" besitzen! Außerdem hat deine XML diverse Rechtschreibfehler sogar in den Knoten die du selektieren willst, deswegen muss ich hier den tatsächlichen Namen mal wieder raten.

Deswegen gehe ich einfach mal von folgender XML-Datei aus (die ist wenigstens valide face-wink)

<?xml version="1.0" encoding="utf-8"?>  
<root>
   <partsmanagement count="1">  
       <part part_one="Wert" part_two="Hallo" part_sixty-five="Test">  
           <whatever />
           <whatever />
       </part>
       <part part_one="Wert"  part_sixty="Test">  
           <whatever />
           <whatever />
       </part>
    </partsmanagement>
</root> 

Falls es dich interessiert wie man mittels XPath bestimmte Knoten selektiert die den gewünschten Kriterien entsprechen (so wie es die Funktion "SelectNodes" hier tut) dann beliest du dich hier
https://www.w3schools.com/xml/xpath_syntax.asp
Im Beispiel Xpath werden nur die "part" Elemente selektiert die auch deine beiden genannten Attribute besitzen
//partsmanagement/part[@part_two and @part_sixty-five]
Nur diese werden geändert und am Ende die XML wieder gespeichert.

ACHTUNG HINWEIS!: Anpassungen könnten nötig werden wenn du uns hier Teile mit XML "Namespaces" in deiner XML verschwiegen hast.

Gruß P.
Atlas2
Atlas2 19.11.2020, aktualisiert am 16.05.2023 um 15:16:19 Uhr
Goto Top
Hallo Printe,

danke für deine Antwort.
Zitat von @Printe:

Kein Thema ... aber lass den "Shiet" mit dem Split face-wink Powerhell kann XML nativ parsen, in Objekte zerlegen und mittels XPath passende Knoten selektieren!
Ok

>$file = 'D:\Datei.xml'  
>$xml = [xml](gc $file)
>$xml.SelectNodes("//partsmanagement/part[@part_two and @part_sixty-five]") | %{  
>    $_.part_two = "$($_.part_two).$($_.'part_sixty-five')"  
>}
>$xml.Save($file)
>

Funktioniert ;) Thx

btw. dein hier gepostetes XML ist übrigens nicht valide, es hat mehrere Root(DocumentElement)-Knoten und das kann eine XML nicht, eine XML kann nur ein einziges "DocumentElement" besitzen!

Dann wird die als XML bezeichnete Datei nicht valide erzeugt.


Falls es dich interessiert wie man mittels XPath bestimmte Knoten selektiert die den gewünschten Kriterien entsprechen (so wie es die Funktion "SelectNodes" hier tut) dann beliest du dich hier
https://www.w3schools.com/xml/xpath_syntax.asp

Das werde ich mir ansehen.
Danke
VG Roachman
Printe
Printe 19.11.2020 aktualisiert um 15:49:54 Uhr
Goto Top
Zitat von @Atlas2:
Dann wird die als XML bezeichnete Datei nicht valide erzeugt.
Kannst es ja einfach mal selbst probieren und folgenden invaliden Code mit zwei DocumentElements ausführen:
[xml]@' 
<?xml version="1.0" encoding="utf-8"?> 
<root>
</root>
<root>
</root>
'@ 

Bringt dir folgende Error-Message

annot convert value "<?xml version="1.0" encoding="utf-8"?>  
<root>
</root>
<root>
</root>" to type "System.Xml.XmlDocument". Error: "Das Dokument verfügt bereits über einen 'DocumentElement'-Knoten."  
At line:1 char:1
+ [xml]@'  
+ ~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) , RuntimeException
    + FullyQualifiedErrorId : InvalidCastToXmlDocument

Wenn das wirklich so wäre könntest du aber meinen obigen Code überhaupt erst gar nicht laufen lassen weil sich der Parser vorher schon beschweren würde. Denke das war nur ein Copy n Paste Fehler von deiner Seite.

Na denn.

Gruß P.
Atlas2
Atlas2 21.11.2020, aktualisiert am 16.05.2023 um 15:16:19 Uhr
Goto Top
Denke das war nur ein Copy n Paste Fehler von deiner Seite.

Das kann so passiert sein face-wink

Noch eine Frage, mir ist aufgefallen das die Umlaute nicht mehr korrekt nach dem Durchlauf dargestellt werden. Wie kann ich das noch ändern?

Danke

VG