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-ID: 305301

Url: https://administrator.de/forum/powershell-und-xmls-von-definierten-xml-tags-die-werte-aendern-305301.html

Ausgedruckt am: 23.12.2024 um 12:12 Uhr

129413
129413 25.05.2016, aktualisiert am 01.06.2016 um 14:49:57 Uhr
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
rdklie
rdklie 25.05.2016 aktualisiert um 12:13:17 Uhr
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
129413
129413 25.05.2016 aktualisiert um 12:55:40 Uhr
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
rdklie
rdklie 25.05.2016 um 17:48:57 Uhr
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
129413
Lösung 129413 25.05.2016 aktualisiert um 18:16:55 Uhr
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
rdklie
rdklie 25.05.2016 um 18:26:41 Uhr
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!!
rdklie
rdklie 01.06.2016 um 11:49:41 Uhr
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
129413
129413 01.06.2016 aktualisiert um 14:47:28 Uhr
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')  
rdklie
rdklie 01.06.2016 um 14:42:08 Uhr
Goto Top
Danke, klappt so aber nicht.

Hab jetzt einfach dasselbe nochmals genommen und statt

('//topmostSubform/*')  

mit

('//topmostSubform/*/*')  

ersetzt. face-smile

LG
129413
129413 01.06.2016 aktualisiert um 14:54:15 Uhr
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.