brooklin
Goto Top

Batch Script, um Variable in allen .xml-Dateien eines Ordners zu ändern

Hallo,
meine einzige Batch-Erfahrung ist robycopy zur LW-Sync; bin Anfänger/Endnutzer.
Benötige ein Batch Script, um den Wert einer Variable in allen xml-Dateien eines Ordners, zu überschreiben. Die Änderungen sind in einer txt-Datei abgelegt -> n xml-Dateien im Verzeichnis und n Zeilen in der txt, die im gleichen Verzeichnis liegt.
xml-Datei:
- Kopf: <?xml version="1.0"?>
- Bsp.-Variable/Wert (old): <E K="Image_City" V="Potsdam" />
- Bsp.-Variable/Wert (new): <E K="Image_City" V="Hamburg" />
Das Script soll "Image_City" suchen und Potsdam durch Hamburg ersetzen, wobei Hamburg aus der txt übernommen wird. Falls Anzahl der xml-Dateien <> Anzahl der txt-Zeilen => Fehlermeldung. Bei Verwendung anderer Variablen soll "Image_City" von mir im Batch händisch geändert werden (kein Menü).
Evtl. gehts einfacher mit notepad++ oder anders; leider nix gefunden.
LG

Content-Key: 33154708189

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

Printed on: June 30, 2024 at 06:06 o'clock

Member: WolleRoseKaufe
Solution WolleRoseKaufe Jun 27, 2024 updated at 20:46:25 (UTC)
Goto Top
#PowerShell
$folder = "e:\daten"  
$txtfile = "e:\daten\werte.txt"  

[string[]]$data = Get-Content -Path $txtfile
$xmlfiles = Get-ChildItem -Path $folder -Recurse -File -Filter *.xml
if ($xmlfiles.Count -ne $data.Count){
    Write-Error -Message "Anzahl an Werten und XML Dateien ist nicht identisch!"  
    return
}
$cnt = 0
foreach($file in $xmlfiles){
    $xml = New-Object XML
    $xml.Load($file.Fullname)
    $found = $false
    foreach($node in $xml.SelectNodes("//E[@K='Image_City']")){  
        [void]$node.SetAttribute("V",$data[$cnt])  
        $found = $true
     }
     If ($found){
        $xml.Save($file.Fullname)
     }
     $cnt++
}

✌️
Member: brooklin
brooklin Jun 27, 2024 at 21:59:53 (UTC)
Goto Top
Ich glaubs nicht, WolleRoseKaufe, grandioses Profiwissen, freizügig hergegeben. Mein Riesendank an Dich!! Heute Abend packe ich es nicht mehr. Aber morgen wird es sofort ausprobiert und werde mich als erstes mit PowerShell befassen müssen. Soweit ich sehe, muß ich nur Zeile 15 ändern, wenn ich die Variable ändern will. LG
Member: brooklin
brooklin Jun 28, 2024 at 15:24:10 (UTC)
Goto Top
Gerade ausprobiert. Das Script läuft fehlerfrei durch und macht, was es soll!! Auch den Fehlerfall habe ich getestet - funktioniert einwandfrei!
Nochmals herzlichen Dank @WolleRoseKaufe - auf Anhieb fehlerfrei, das ist schon große Klasse.
Noch ein Schönheitsfehler, der an mir lag: Meine xml-Dateien haben die Endung .cos. Damit das Skript läuft habe ich die Dateien in .xml umbenannt und danach wieder in .cos. Es ist mir nicht gelungen, das Skript an .cos-Dateien anzupassen, um die Umbennerei zu umgehen (alle xml formal in cos umbenannt). Könnte da nochmal jemand helfen? Danke!
LG
Member: WolleRoseKaufe
Solution WolleRoseKaufe Jun 28, 2024 updated at 15:38:39 (UTC)
Goto Top
Noch ein Schönheitsfehler, der an mir lag: Meine xml-Dateien haben die Endung .cos. Damit das Skript läuft habe ich die Dateien in .xml umbenannt und danach wieder in .cos. Es ist mir nicht gelungen, das Skript an .cos-Dateien anzupassen, um die Umbennerei zu umgehen (alle xml formal in cos umbenannt). Könnte da nochmal jemand helfen? Danke!

Zeile 5 einfach nur den Filter auf "*.cos" anpassen, that's it.
$xmlfiles = Get-ChildItem -Path $folder -Recurse -File -Filter *.cos
👌
Member: brooklin
brooklin Jun 28, 2024 at 16:26:24 (UTC)
Goto Top
Herzlichen Dank für die nochmalige Hilfe!!
LG
Member: brooklin
brooklin Jun 28, 2024 at 16:52:27 (UTC)
Goto Top
@WolleRoseKaufe: Zeil 5 ändern = alles okay, Zeile 7 ändern in "Anzahl an Werten und COS Dateien ist nicht identisch!" auch gut.
ABER: Beim Test für die Stadt "Würzburg" kennt der Zeichensatz die dt. Umlaute nicht und schreibt "Würzburg". Hat irgendwas mit ASCII vs. Unicode zu tun... Kann man das noch einstellen??
Member: WolleRoseKaufe
WolleRoseKaufe Jun 28, 2024 updated at 19:29:22 (UTC)
Goto Top
Deine XML Dateien sollten das Encoding hinterlegt haben, denn sonst weiß die PowerShell nicht welches Encoding sie annehmen soll und verwendet automatisch UTF-8, also entweder das korrekte Encoding in der Xml-Declaration hinterlegen und die Dateien auch im entsprechenden Encoding abspeichern
<?xml version="1.0" encoding="utf-8"?> 
Oder dem XML Object das korrekte Encoding mitgeben sofern alle Dateien das gleiche Encoding aufweisen:
$xml = [xml](Get-Content -Path $file.Fullname -Encoding Default)
Das Schlüsselwort "Default" bezeichnet den Standard unter Windows (ANSI Codepage 1252), falls das nicht das Encoding der Dateien entspricht bitte anpassen.

Unter Windows muss man auch noch aufpassen das man das Powershell-Skript selbst als UTF-8 mit BOM (ByteOrderMark) abspeichert damit evt. Strings mit Umlauten im Skript richtig interpretiert und weitergegeben werden.
Member: brooklin
brooklin Jun 29, 2024 at 09:52:49 (UTC)
Goto Top
@WolleRoseKaufe:
Version 1: die xml-Declaration in der Originaldatei ändern sollte ich nicht tun, da von übergeordnetem Programm erzeugt und weiterverarbeitet wird
Version 2: $xml=... mit Schlüsselwort "Default" habe ich nach Zeile 12 in das Script eingefügt und die Kodierung des Script auf UTF-8 [soll wohl mit BOM bedeuten] in Notepad++ 7.3 gesetzt. Funktioniert aber nicht.
Vermutlich muß ich mit der Zeile $xml = [xml](Get-Content -Path $file.Fullname -Encoding Default) etwas anderes tun, aber was?
Member: WolleRoseKaufe
WolleRoseKaufe Jun 29, 2024 updated at 10:38:01 (UTC)
Goto Top
Version 2: $xml=... mit Schlüsselwort "Default" habe ich nach Zeile 12 in das Script eingefügt
Nein, diese Zeile muss die Zeilen 12 und 13 komplett ersetzen!
Das "Default" musst du an die tatsächliche Kodierung der XML-Dateien anpassen! Wenn diese also bspw. in UTF8 kodiert sind kommt da auch "UTF8" hin. Mögliche Werte kannst du in der PowerShell ISE per Intellisense sehen oder in der Doku nachlesen.


und die Kodierung des Script auf UTF-8 [soll wohl mit BOM bedeuten]
Nein, UTF8 ist nicht automatisch mit BOM, das muss explizit ausgewählt werden!

Beließ dich mal zu BOM
https://de.m.wikipedia.org/wiki/Byte_Order_Mark

Vermutlich muß ich mit der Zeile $xml = [xml](Get-Content -Path $file.Fullname -Encoding Default) etwas anderes tun, aber was?
S.o.
Member: brooklin
brooklin Jun 29, 2024 at 17:22:42 (UTC)
Goto Top
Habe alles mehrfach gelesen und die unterschiedlichsten Varianten ausprobiert:

- $xml = [xml](Get-Content -Path $file.Fullname -Encoding Default) für Zeile 12 und 13 eingesetzt
- Notepad++ v.7.3.1 hat 3 Haupt-Varianten der Kodierung: ANSI, UTF-8, UTF-8 ohne BOM
=> das Script mit UTF-8 abgespeichert (auch mit Konvertiere zu UTF-8 ausprobiert)

- die Kodierung der Original-xml-Datei ist UTF-8 ohne BOM
=> $xml = [xml](Get-Content -Path $file.Fullname -Encoding utf8NoBOM) eingesetzt

=> Fehlermeldung: Get-Content : Der Parameter "Encoding" kann nicht gebunden werden usw.

Danach etliche anderen Varianten ausprobiert -> entweder die dt. Umlaute werden nicht erkannt oder es gibt eine Fehlermeldung.
Es muß noch eine andere Ursache geben. Any idea?
Member: WolleRoseKaufe
WolleRoseKaufe Jun 29, 2024 updated at 18:34:33 (UTC)
Goto Top
Es muß noch eine andere Ursache geben. Any idea?
Nö works as designed. Du hast 100%ig keine durchgehende korrekte Encoding Pipeline.
Nach 15 Jahren PS Erfahrung kann ich das behaupten, ist ein typischer PS-Anfängerfehler (s. Links unten)
Fehlermeldung: Get-Content : Der Parameter "Encoding" kann nicht gebunden werden usw.
Nur neuere PowerShell Versionen akzeptieren neuere Encoding Varianten deswegen die Fehlermeldung (RTFM!). Wenn es aber tatsächlich UTF8 ist reicht hier aber i.d.R. das Encoding UTF8 bei Get-Content, egal ob BOM oder nicht. Vorausgesetzt in der Quelle wurden die Umlaute auch schon richtig kodiert und nicht schon durch die Konvertierung verhunzt.

Du kannst mir aber gerne mal so eine XML-Datei im Original und das Skript ebenfalls unverändert zukommen lassen (PN) dann sehe ich mir mal an ob es an der Quelle liegt oder am Encoding deines Skriptes.

Um sicher zu gehen erstelle das PS Skript mal in der PowerShell ISE statt mit Notepad++.

Das Problem kommt hier immer wieder, und wird von Anfängern immer wieder erlebt, also nichts weltbewegendes man muss es nur richtig machen ...

Powershell System.Xml.XmlDocument Umlaute
Powershell Variable wird mit falschem Encoding ausgegeben