rdklie
Goto Top

Powershell und XMLs -Von definierten XML Tags die Werte ändern

Hallo Zusammen

Ich steh wohl grad bisschen auf dem Schlauch.

Ich habe ein XML mit folgendem Aufbau:

<?xml Version="1.0" encoding="UTF-8" standalone="yes"=> 
<topmostSubform>
<f1_04_0_>9000</f1_04_0_>
<f1_05_0_>100000</f1_05_0>
.
.
.
<f4_36_0_>1234567</f4_36_0_>
<f3_25_0_>112233</f4_36_0_>
</topmostSubform>

Ziel dieser Übung ist es nun, die Werte (100000,1234567) anhand den zuvor definierten Xml-Tags (<f1_05_0_>, <f4_36_0_>) zu formatieren, dass die Werte folgende ins XML geschrieben werden: 100,000,1,234,567.

Soa.. Werte auslesen klappt, formatieren auch.. Was mir aktuell noch schleierhaft ist, wie ich auf die XML Tags abfragen kann. Mit dem Beispiel des Tags <f4_36_0_> als $xmltag, $xml = get-content xmlpfad..:
foreach($xmltag in $xml.topmostSubform.[??])
{
lese den wert aus, falls mehr als 3 stellen setzte Kommas und schreibs zurück
}

Nun weiss aber nicht, wie ich dieses Foreach so setzen kann das auf die Tag's eingegangen wird? aktuell erscheinen mir nur immer die Werte...

Wisst ihr Rat?

Beste Grüsse

Content-Key: 305301

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

Printed on: April 29, 2024 at 03:04 o'clock

Mitglied: 129413
129413 May 25, 2016, updated at Jun 01, 2016 at 12:49:57 (UTC)
Goto Top
Zuerst mal dein XML ist absolut nicht regelkonform und enthält diverse Fehler (in der Deklaration und Start und Endtags stimmen nicht überein):

Nun weiss aber nicht, wie ich dieses Foreach so setzen kann das auf die Tag's eingegangen wird? aktuell erscheinen mir nur immer die Werte...

Beispiel (der XML-Code ist nur zum Beispiel als Variable eingebunden):
[xml]$xml = @" 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<topmostSubform>
<f1_04_0_>9000</f1_04_0_>
<f1_05_0_>100000</f1_05_0_>
<f4_36_0_>1234567</f4_36_0_>
<f3_25_0_>112233</f3_25_0_>
</topmostSubform>
"@ 

# Knoten unterhalb von topmostSubform durchlaufen
$xml.SelectNodes('//topmostSubform//*') | %{ 
    "Name des Knotens: " + $_.Name 
    "Wert des Knotens: " + $_.innerText 
}
Alternativ für die Schleife auch:
$xml.topmostSubform.ChildNodes | %{
    "Name des Knotens: " + $_.Name  
    "Wert des Knotens: " + $_.innerText  
}
Gruß skybird
Member: rdklie
rdklie May 25, 2016 updated at 10:13:17 (UTC)
Goto Top
Hi skybird

Erstmal vielen Dank für deine Antwort.
Jep, das XML ist echt bullsh*t (sorry für die Wortwahl).. Ist aber leider ein export aus Acrobat. Leider muss ich wirklich die zu formatierenden Tags angeben, ansonsten werden Postleitzahlen auch formatiert face-smile

Hier mal mein aktuelles Script mit dem oben genannten Beispiel:
$xml = [xml](get-content C:\temp\xml.xml)
$tags = 'f1_05_0_,f4_36_0_'  
$arr = $tags -split(',')  
$arr2 = $xml.topmostSubform.Childnotes | % { $_.Name}

foreach($arr in $arr2)
{ write-host "Hello World" }  

Nun, wenn ich folgende Zeile eingebe, stimmt das ausgegebene Resultat:
$xml.topmostSubform.Childnotes | % { $_.Name}
Es erscheinen nur die Tag's bzw deren Bezeichnung (ohne <> drumrum)

wenn ich aber das ganze Skript laufen lassen, erhalte ich zuviele "Hello World"'s .. Ich glaub langsam ich machs zu kompliziert face-smile Das Ziel wäre ja 2x "Hello World" ..

Lg
Mitglied: 129413
129413 May 25, 2016 updated at 10:55:40 (UTC)
Goto Top
Zitat von @rdklie:
Erstmal vielen Dank für deine Antwort.
Jep, das XML ist echt bullsh*t (sorry für die Wortwahl).. Ist aber leider ein export aus Acrobat. Leider muss ich wirklich die zu formatierenden Tags angeben, ansonsten werden Postleitzahlen auch formatiert face-smile
Dein Code ist aber leider auch nicht besser,, Stichwort Schreibfehler: Childnotes...
Nun, wenn ich folgende Zeile eingebe, stimmt das ausgegebene Resultat:
$xml.topmostSubform.Childnotes | % { $_.Name}
Es erscheinen nur die Tag's bzw deren Bezeichnung (ohne <> drumrum)
Ja nee, wenn dann so:
$arr2 = $xml.topmostSubform.Childnodes
foreach($x in $arr2){
   "Nodename: " + $x.Name  
   "Nodewert: " + $x.innerText  
}
Itteriere über das Objekt nicht über Strings!
langsam ich machs zu kompliziert face-smile
Nein du hast nur anscheinend kein Verständnis für die Objekte in der Shell ...

Das %{} das ich oben verwendet habe ist auch nur eine Abkürzung für eine Foreach-Schleife face-smile
Member: rdklie
rdklie May 25, 2016 at 15:48:57 (UTC)
Goto Top
Hallo

Sorry, das war ein Abtippfehler da die Internetumgebung kein Copy& Past zulässt.

Es kann gut sein das ich über kein Verständnis verfüge.. deshalb frag ich face-smile

Also, aktueller Code:
$xml = [xml](get-content C:\temp\xml.xml) 
$arr = $xml.topmostSubform.Childnodes
foreach($x in $arr)
{
 $tags = 'f1_05_0_,f4_36_0_'   
 $arr2 = $tags -split(',')   
 $formatiert = "{0:0,0}" -f $x.innertext  
if ($arr2 -eq $x.name)
{$xml | foreach-object {$_ -replace $x.InnerText, $formatiert | set-content C:\temp\xml.xml}
else
{}
}

So in etwa stell ich mir das vor.. Das resultat im XML ist dann aber jeweils #document - Rest ist weg.

Kannst du mir allenfalls weiterhelfen?

Beste Grüsse
Mitglied: 129413
Solution 129413 May 25, 2016 updated at 16:16:55 (UTC)
Goto Top
OK jetzt ist mir einiges klarer was du tatsächlich machen willst. Das lässt sich auf das hier verkürzen
$xml = [xml](get-content 'C:\temp\xml.xml')   
$xml.topmostSubForm.childNodes | ?{$_.Name -in @('f1_05_0_','f4_36_0_')} | %{  
    $_.innerText = "{0:0,0}" -f [int32]$_.innertext   
}
$xml.Save('C:\temp\xml_fertig.xml')  
Achte auf deine Powershell-Version den Operator -in gibt es erst ab Powershell Version 3.0
Member: rdklie
rdklie May 25, 2016 at 16:26:41 (UTC)
Goto Top
Wow, dachte echt nicht das man das so verschachteln kann.

Lesen kann ich den Code. Aber darauf wäre ich wohl nie gekommen.

Skybird, vielen lieben Dank!!
Member: rdklie
rdklie Jun 01, 2016 at 09:49:41 (UTC)
Goto Top
Hallo skybird

Darf ich dich nochmal belästigen?

In dem kack XML, sind noch gewisse Tags folgend drin :
<f1_05_0_>1000000</f1_05_0_>
<Line1>
     <f4_36_0_>123456</f4_36_0_>
</Line1>
<Line2>
    <f4_37_0_>123456</f4_37_0>
</Line2>

usw..
Kann man das Durchsuchen der Childnotes noch auf die ChildChildnotes ausweiten?

LG
Mitglied: 129413
129413 Jun 01, 2016 updated at 12:47:28 (UTC)
Goto Top
Das passende Beispiel dafür hatte ich ganz zu Anfang gepostet:

Nutze XPath
$xml = [xml](get-content 'C:\temp\xml.xml')   
$xml.SelectNodes('//topmostSubform//*') | ?{$_.Name -in @('f1_05_0_','f4_36_0_')} | %{  
    $_.innerText = "{0:0,0}" -f [int32]$_.innertext   
}
$xml.Save('C:\temp\xml_fertig.xml')  
Member: rdklie
rdklie Jun 01, 2016 at 12:42:08 (UTC)
Goto Top
Danke, klappt so aber nicht.

Hab jetzt einfach dasselbe nochmals genommen und statt

('//topmostSubform/*')  

mit

('//topmostSubform/*/*')  

ersetzt. face-smile

LG
Mitglied: 129413
129413 Jun 01, 2016 updated at 12:54:15 (UTC)
Goto Top
Nö das Sternchen erfasst alle Knoten auch weitere Subnodes!! Du hast einen Slash hinter topmostSubform vergessen s.o. ...
('//topmostSubform//*')
Dann werden wirklich alle Knoten rekursiv unterhalb 'topmostSubForm' durchsucht, bei deiner Variante nur zwei Level.