xml PowerShell Element Attribut-Namen ändern?

1 Antwort

Prinzipiell ist es eine schlechte Idee in XML herumzuschreiben. XML kann komplexe Datenstrukturen/Objecte repräsentieren, welche ziemlich empfindlich auf willkürliche Änderungen durch Textoperationen reagieren. Normalerweise wäre der richtige Weg die XML in Powershellobjecte zu konvertieren die nötigen Änderungen am Object vorzunehmen und die Objekte wieder als XML zu speichern. das kann allerdings bei komplexen Objecten recht kompliziert werden.

Mit Deinem kurzen Schnipsel aus deinem XML kann ich wirklich nur automatisierte "Textverarbeitung machen. Das Problem dabei, XML muss nicht Zwangsläufig Zeilenbasiert gespeichert sein und es gibt zusätzlich noch Unterschide bei den Zeilenvorschüben bei Unix(Linux,Apple) und Windows .

Mit der .Net .Replace()-Methode kommst Du da nicht weit. Powershells replace-Operator ist hingegen extrem mächtig. Man muss nur Regex-Grouping beherrschen.

mein test pseudo xml text, damit ich sehe, dass mein Regex mit verschiedenen Formatierungen fertig wird:

demo.xml

<TimeLine startutc="2023-07-22 06:00">
  <Blubb duration="0815" type="plobbb" />
</TimeLine>
<TimeLine startutc="2023-07-15 06:00">
  <Activity duration="33899" type="Rest" />
</TimeLine>
<TimeLine startutc="2023-07-15 06:00"><Activity duration="33899" type="Rest" /><Blubb duration="0815" type="plobbb" /></TimeLine>

test.ps1

$quelle = '.' # zum Testen  nur  der aktuelle Ordner
$allXmlDateien = Get-ChildItem $quelle "*.xml"
foreach ($datei in $allXmlDateien) {
    Write-Host $datei.FullName -fo green
    $text = Get-Content $datei.FullName
    $text = $text -replace '(Activity)(.+?)(type)(\=.+?\/\>)','ActivityName$2ActivityType$4'
    $text  #den neuen Texte anzeigen (das schreiben in die Datei  bekommst Du selbst  gebacken)
    #Set-Content $datei.FullName $text
    Write-Host nächste  Datei [Enter] -fo mag
    pause  
}

nun mal das Herzstück erklärt:

der replace-Operator von Powershell arbeitet mit RegEx. in ganzen reagiert:

'(Activity)(.+?)(type)(\=.+?\/\>)'

auf folgenden String

  • Activity
  • ein/mehr so wenig wie möglich beliebige Zeichen
  • type
  • =zeichen ein/mehr so wenig wie möglich beliebige Zeichen /zeichen >zeichen

Damit ich später unbekannte Teile des gefundenen Strings in den Zielstring übernehmen kann binde ich die einzelnen Abschnitte in Gruppen. Diese Gruppen kann ich mit $Nummer im Zielstring einfügen ohne deren wert zu kennen.

für den String <Activity duration="33899" type="Rest" />  währe der Inhalt der Gruppen:

  • $0 'Activity duration="33899" type="Rest" />'
  • $1 'Activity'
  • $2 ' duration="33899" '
  • $3 'type'
  • $4 '="Rest" />'

der Zielstring 'ActivityName$2ActivityType$4' ist entsprechend: 'ActivityName duration="33899" ActivityType="Rest" />' . Die Gruppen $2 und $4 werden unverändert übernommen.

Achtung! Die verwendeten Gruppenvariablen $x haben nichts mit den Powershellvariablen $var zu tun und sind in nur in der aktuellen Regexoperation gültig!

Ich empfehle Dir in jedem Fall , vor dem Zurückschreiben der geänderten Daten in die Orginaldateien, von diesen eine Sicherheitskopie anzulegen.

Wie Eingangs erwähnt, kann ich bei nackten Textoperationen auf XML-nicht garantieren, das diese von den Applikationen akzeptiert werden, welche diese nutzen.

noch etwas Lektüre zu dem RegEx-Kram:

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren
nogpsfake 
Fragesteller
 30.07.2023, 09:27

Hallo Erzesel,

Danke erstmal für die angebotene Lösung, die super funktioniert. Ich bin mit der Powershell bzw. dem CLI nur sehr wenig vertraut, da ich generell erst sehr spät (48) mit programmieren angefangen habe und damit auch zwangsläufig mal mit der PS arbeiten muss.

Bei den Dateien handelt es sich um nicht kritische Dateien. Wichtig ist hier nur die Struktur. Die XML werden später mit einem anderen Programm in Containerdateien umgewandelt und wenn die Struktur nicht stimmt, dann gibt's halt keinen Container :). Die XML Dateien werden von mir generiert um Test-Container zu erhalten. Das Problem war nur, dass ein Entwickler ein neues Tool geschrieben hat, mit einer neuen XML-Struktur und ich meine alten Dateien auf die neue Struktur umstellen möchte.

Ich hatte es zuerst auch mit Objekten und deren Bearbeitung versucht, bin aber kläglich gescheitert, mangels Kenntnissen. :-) Und das die Textverarbeitung nicht die richtige bzw. beste Lösung ist, habe ich ja festgestellt und diesen Thread hier erstellt. :-)

Powershells replace-Operator ist hingegen extrem mächtig. Man muss nur Regex-Grouping beherrschen.

Das werde ich mir auf jeden Fall mal genauer anschauen. Von dem Grouping z.B. hatte ich noch gar nichts gehört.

Vielen Dank erstmal für die Hilfe.

Daniel

0