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

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

Ausgedruckt am: 21.11.2024 um 17:11 Uhr

13676056485
Lösung 13676056485 27.06.2024, aktualisiert am 01.07.2024 um 14:20:55 Uhr
Goto Top
#PowerShell
$folder = "e:\daten"  
$txtfile = "e:\daten\werte.txt"  

[string[]]$data = Get-Content -Path $txtfile -Encoding Default
$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++
}

✌️
brooklin
brooklin 27.06.2024 um 23:59:53 Uhr
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
brooklin
brooklin 28.06.2024 um 17:24:10 Uhr
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 @13676056485 - 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
13676056485
Lösung 13676056485 28.06.2024 aktualisiert um 17:38:39 Uhr
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
👌
brooklin
brooklin 28.06.2024 um 18:26:24 Uhr
Goto Top
Herzlichen Dank für die nochmalige Hilfe!!
LG
brooklin
brooklin 28.06.2024 um 18:52:27 Uhr
Goto Top
@13676056485: 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??
13676056485
Lösung 13676056485 28.06.2024 aktualisiert um 21:29:22 Uhr
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.
brooklin
brooklin 29.06.2024 um 11:52:49 Uhr
Goto Top
@13676056485:
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?
13676056485
Lösung 13676056485 29.06.2024 aktualisiert um 12:38:01 Uhr
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.
brooklin
brooklin 29.06.2024 um 19:22:42 Uhr
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?
13676056485
Lösung 13676056485 29.06.2024 aktualisiert um 20:34:33 Uhr
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
brooklin
brooklin 01.07.2024 um 14:15:10 Uhr
Goto Top
@13676056485:
Sorry, habe die Antwort erst jetzt gesehen.
Für PowerShell ISE muß ich mir Zeit nehmen, das zu installieren und anzuwenden (vor 4 Tagen wußte ich nicht mal, daß es PowerShell gibt).
Die txt-Datei ist in UTF-8 kodiert. Ich würde sie in UTF-8 mit BOM umkodieren und alle Versuche nochmals wiederholen. Aber erst später heute.
Wenn es dann nicht klappt - sende ich die Dateien per PN - sehe aber keine Möglichkeit, eine Datei anzuhängen; sende dann einen Google-Drive-Link. Danke.
13676056485
Lösung 13676056485 01.07.2024 aktualisiert um 14:34:01 Uhr
Goto Top
Zitat von @brooklin:

@13676056485:
Sorry, habe die Antwort erst jetzt gesehen.
Für PowerShell ISE muß ich mir Zeit nehmen, das zu installieren und anzuwenden
Die musst du nicht installieren die ist standardmäßig an Bord von Windows.
Die txt-Datei ist in UTF-8 kodiert. Ich würde sie in UTF-8 mit BOM umkodieren und alle Versuche nochmals wiederholen.
Bei der Textdatei ist das BOM nicht zwingend nötig, nur für eine automatische Erkennung von Get-Content. Gib die Kodierung beim Laden der Textdatei ebenfalls explizit an, in dieser Zeile
[string[]]$data = Get-Content -Path $txtfile -Encoding UTF8
brooklin
brooklin 01.07.2024 um 14:37:35 Uhr
Goto Top
Ähm, das ist die Zeile 4 Deiner bisherigen PS-Datei, d.h. nix ändern...
13676056485
Lösung 13676056485 01.07.2024 aktualisiert um 14:44:46 Uhr
Goto Top
Zitat von @brooklin:

Ähm, das ist die Zeile 4 Deiner bisherigen PS-Datei, d.h. nix ändern...
Das habe ich oben vorhin noch nachgetragen damit anderer nicht auch in die Falle tappen.
brooklin
brooklin 01.07.2024 um 18:22:43 Uhr
Goto Top
@13676056485:
Erfolg!! Hatte wegen Deines Default-Ersatz-Parameters (UTF8) nochmal nachgelesen:
https://learn.microsoft.com/de-de/powershell/module/microsoft.powershell ...
-> das ist genau der MIT BOM, wie Du schon vorher gesagt hattest!
M.E. hatte ich den mehrfach mit Notepad++ ausprobiert - mit ISE hats endlich geklappt.
Das Ganze läßt sich vom Desktop mit Doppelklick starten:
%windir%\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -File d:\_select\Image_City-ISE-wt_BOM.ps1
Ist das korrekt und wie kann ich mehrere PS-Dateien in einem Rutsch nacheinander starten (ich will mehrere Parameter mit Deinem Skript ändern)??
LG