none
XML Dateien bearbeiten RRS feed

  • Frage

  • Halllo @ All,

     

    ich versuche eine XML Datei zu bearbeiten via Power Shell, aber ich bekomm das irgendwie nicht hin.

     

    <?xml version="1.0" encoding="Windows-1252"?>
    
    <UserNotifications>
    
      <Install lang="de-DE" colorscheme="blue" icon="Blueshield" showtrayicon="true">
    
        <Caption>Aktualisierung</Caption>
    
        <Instruction>Beenden Sie ZZZ, um die Aktualisierung zu starten.</Instruction>
    
        <Description>Für die Aktualisierung ist das Schließen von ZZZ erforderlich. Stellen Sie sicher, dass Sie alle Daten gespeichert haben.</Description>
    
        <RemindLater>Später erinnern:</RemindLater>
    
        <RemindLaterButton>Später durchführen</RemindLaterButton>
    
        <ActionButton>Installation starten</ActionButton>
    
        <SkipText>Sind Sie sicher, dass Sie die Installation abbrechen wollen?</SkipText>
    
        <AutoCloseText>Start in: {0} Min, {1} Sek.</AutoCloseText>
    
        <ProcessClose>XXX</ProcessClose>
    
      </Install>
    
      <Install lang="en-US" colorscheme="blue" icon="Blueshield" showtrayicon="true">
    
        <Caption>Software Update</Caption>
    
        <Instruction>Close ZZZ in order to start the update</Instruction>
    
        <Description>To start the update it is necessary to close ZZZ. Please assure that all data has been saved, if needed.</Description>
    
        <RemindLater>Remind me in:</RemindLater>
    
        <RemindLaterButton>Postpone</RemindLaterButton>
    
        <ActionButton>Install now</ActionButton>
    
        <SkipText>Are you sure you want to cancel the installation?</SkipText>
    
        <AutoCloseText>Starting in: {0} min, {1} sec</AutoCloseText>
    
        <ProcessClose>XXX</ProcessClose>
    
      </Install>
    
      <Uninstall lang="de-DE" colorscheme="blue" icon="Blueshield" showtrayicon="true">
    
        <Caption>Software-Aktualisierung</Caption>
    
        <Instruction>Beenden Sie ZZZ, um die Deinstallation zu starten.</Instruction>
    
        <Description>Für die Deinstallation ist das Schließen von ZZZ erforderlich. Stellen Sie sicher, dass Sie alle Daten gespeichert haben.</Description>
    
        <RemindLater>Später erinnern:</RemindLater>
    
        <RemindLaterButton>Später durchführen</RemindLaterButton>
    
        <ActionButton>Deinstallation starten</ActionButton>
    
        <SkipText>Sind Sie sicher, dass Sie die Installation abbrechen wollen?</SkipText>
    
        <AutoCloseText>Start in: {0} Min, {1} Sek.</AutoCloseText>
    
        <ProcessClose>XXX</ProcessClose>
    
      </Uninstall>
    
    </UserNotifications>
    
    


     

    Ich möchte gerne alle Einträge ändern von ZZZ nach z.B. Firefox.

    Des Weiteren möchte ich gerne das alle XXX Einträge geändert werden und wenn mehrere Prozesse beendet werden sollen, dann muss noch einen Zeile Hinzugefügt werden.

    <ProcessClose>Firefox</ProcessClose>

    <ProcessClose>Office</ProcessClose>

    <ProcessClose>Notepad</ProcessClose>

     

    Könnte mir da evtl. jemand helfen?

     

    Gruß

    Markus

     

     

    Dienstag, 1. März 2016 18:56

Antworten

  • Hallo,

    Das ersetzten der XXX in ProcessClose könntest du mit:

    [xml]$xmlfile = Get-Content 'File.xml'
    
    $xmlfile.Usernotifications.Install|% {if ($_.ProcessClose -eq 'XXX'){$_.ProcessClose = 'XYZ'}}

    erledigen.

    Das einfügen von neuen ProcessClose Eigenschaften würde ich auch über xml erledigen. Am besten mit clone und dann Append:

    $clone = (($xmlfile.UserNotifications.Install.ChildNodes|? `#text -eq 'XXX')[0]).Clone()
    $clone.'#text' = 'ABC'
    $xmlfile.UserNotifications.Install[0].AppendChild($clone)

    Das ersetzen von ZZZ würde ich auch über replace lösen. Replace sollte eigentlich in Powershell 3 verfügbar sein. Laut about_Comparison_Operators seit Powershell 2. Probiere es doch mal mit -replace statt .replace. Würde mich interessieren, ob das bei dir einen Unterschied macht.

    MfG Jan-Henrik



    Mittwoch, 2. März 2016 09:52
  • Hallo,

    Hab es jetzt hinbekommen.


    $Prozesse = ""
    $Ausgabe = ""
        $CurrentXMLFile = 'C:\File.xml'
        [xml]$xmlfile = Get-Content ($CurrentXMLFile)
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Install[@lang='de-DE']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Install[@lang='en-US']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Uninstall[@lang='de-DE']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Uninstall[@lang='en-US']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
    $Prozesse="Winword.exe,Notepad.exe,Firefox.exe"
    $Ausgabe=$Prozesse -split ","
    
    foreach ($i in $Ausgabe){
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Install[@lang='de-DE']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Install[@lang='en-US']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Uninstall[@lang='de-DE']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Uninstall[@lang='en-US']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    }
    
        $xmlfile.Save($CurrentXMLFile

    Vielleicht kann man das noch besser umsetzten, da ich aber noch ein newbie bin in PS, hab ich das nicht besser hinbekommen.

    Hallo Jan,
    Danke nochmal für die Unterstützung, da es ein teil der Lösung war.

    Gruss
    Markus

    PS. Vielleicht kann mir ja mal jemand das hier erklären, dies ist sehr nervig, ob wohl hier mehr als 4 Zeichen und weniger als 60.000 Zeichen sind. Daher istd er Text jetzt kurz gefasst vorher waren es knapp 3000 Zeichen mit Code.


    Dienstag, 8. März 2016 10:11

Alle Antworten

  • das erste habe ich ich:

    $xmlfile = "C:\TMP\TEST.XML"
    $xmlDoc = [xml](Get-Content -Path $xmlfile) #XML Einlesen
    
    $xmlNode = $xmlDoc.SelectSingleNode("UserNotifications/Install[@lang='de-DE']/Instruction")
    $xmlNode.InnerText = "Beenden Sie Software1, um die Aktualisierung zu starten."
    $xmlDoc.Save($xmlfile) #XML Speichern


    Ich hatte auch versucht dies so zu lösen

    $xmlfile = "C:\TMP\TEST.XML"
    $temp = Get-Content $xmlfile
    $temp.replace("ZZZ","Software1") | out-file $xmlfile -force

    Leider bekomm ich da ein Fehlermeldung

    [System.Object[]] keine Methode mit dem Namen "replace" enthält.

    Kann es sein das es unter PS 4.0 geht?

    Auf jedenfall geht der erste schritt. Mag vielleicht umständlich sein, aber es geht.

    Nun muss ich noch das mit dem Prozessen hinbekommen.


    • Bearbeitet mku72 Mittwoch, 2. März 2016 08:26
    Mittwoch, 2. März 2016 08:20
  • Hallo,

    Das ersetzten der XXX in ProcessClose könntest du mit:

    [xml]$xmlfile = Get-Content 'File.xml'
    
    $xmlfile.Usernotifications.Install|% {if ($_.ProcessClose -eq 'XXX'){$_.ProcessClose = 'XYZ'}}

    erledigen.

    Das einfügen von neuen ProcessClose Eigenschaften würde ich auch über xml erledigen. Am besten mit clone und dann Append:

    $clone = (($xmlfile.UserNotifications.Install.ChildNodes|? `#text -eq 'XXX')[0]).Clone()
    $clone.'#text' = 'ABC'
    $xmlfile.UserNotifications.Install[0].AppendChild($clone)

    Das ersetzen von ZZZ würde ich auch über replace lösen. Replace sollte eigentlich in Powershell 3 verfügbar sein. Laut about_Comparison_Operators seit Powershell 2. Probiere es doch mal mit -replace statt .replace. Würde mich interessieren, ob das bei dir einen Unterschied macht.

    MfG Jan-Henrik



    Mittwoch, 2. März 2016 09:52
  • Hallo Jan-Henrik,

    danke für die Antwort.

    das mit dem -replace geht nun, ist auch viel besser somit ist das script bzw. Formular um 130 zeilen kürzer :-) :-O

    das erste mit dem ProcessClose

    [xml]$xmlfile = Get-Content 'File.xml'
    
    $xmlfile.Usernotifications.Install|% {if ($_.ProcessClose -eq 'XXX'){$_.ProcessClose = 'XYZ'}}

    Funktioniert auch super :-).
    Nur das mit dem zweiten geht noch nicht, da ich noch ein newbie bin in PS, finde ich da nicht den Fehler.
    Mir fällt nur auf das nach dem Fragezeichen "`#text" steht damit ist doch hinter dem # alles dokumentiert.
    Wenn ich nun die # rausnehmen dann meckert er das die #Text-Eigenschaft nicht findet, was ich auch irgendwie verstehe.

    Könntest Du mir nicht nochmal auf die Sprünge helfen?

    Trotzdem schonmal viele tausend dank.

    Markus

    Mittwoch, 2. März 2016 10:53
  • Hallo Markus,

    Das ist ein Fehler vom Highlighting hier im Forum. Powershell erkennt beim erstellen der des XML Objektes ($xmlfile) den Typ der ChildNodes als '#text'. Deswegen hatte ich die Raute mittels "`" escaped. Du kannst die Eigenschaft einsehen, indem du

    $xmlfile.UserNotifications.Install.ChildNodes

    eingibst. Dann sollte ganz oben der Spaltenname "#text" lauten. Falls diese Spalte bei dir anders heißt, musst du das entsprechend anpassen. Zur Übersichtlichkeit kanst du die Zeile auch so anpassen, dann ist die Eigenschaft in Anführungsstrichen.

    ($xmlfile.UserNotifications.Install.ChildNodes|? '#text' -eq 'XYZ')

    MfG Jan-Henrik


    Mittwoch, 2. März 2016 11:05
  • Hallo Jan,

    okay, so halbwegs verstanden, nachdem ich einige Seiten durchgelesen habe.

    Nur leider, wenn ich

    $xmlfile.UserNotifications.Install.ChildNodes

    aufrufe kommt nichts.

    Habe die mal mit einer anderen XML Datei versucht wo völlig was andere drin steht, da geht es das er mir die Eigenschaften anzeigt.

    Das Problem hatte ich irgendwie schon bei der ZZZ variante, daher hatte ich dann später

    $xmlNode = $xmlDoc.SelectSingleNode("UserNotifications/Install[@lang='de-DE']/Instruction")

    aufgerufen, da ich nicht anders an die Informationen rankam.

    Warum das so ist weiß ich leider nicht.

    Hast Du ggf. eine Idee, woran das liegen könnte?

    Gruß

    Markus


    • Bearbeitet mku72 Mittwoch, 2. März 2016 13:51
    Mittwoch, 2. März 2016 13:51
  • Hi Markus,

    Wenn du

    [xml]$xmlfile = Get-Content C:\XXX\File.xml
    $xmlfile.UserNotifications.Install.ChildNodes

    alleine mit exakt der XML Datei aus deinem ersten Post ausführst, musst du irgendeinen Output bekommen. Prüfe sonst bitte einmal den Pfad und ob überhaupt etwas in der Variable $xmlfile steht. Wenn du nur $xmlfile ausgibst und dann nicht etwas auftaucht, was ähnlich dem hier ist

    $xmlfile
    
    xml                                   UserNotifications
    ---                                   -----------------
    version="1.0" encoding="Windows-1252" UserNotifications

    ist beim einlesen etwas schief gelaufen. dann bitte einmal die Berechtigungen auf die Datei prüfen.

    MfG Jan-Henrik



    Freitag, 4. März 2016 11:33
  • Markus, wenn dein Problem gelöst ist, markiere bitte noch Jans Antwort "als Antwort".

     


    Blog: http://bytecookie.wordpress.com

    Kostenloser Powershell Snippet Manager v4: Link ! Neue Version !
    (Schneller, besser + komfortabler scripten.)

    Hilf mit und markiere hilfreiche Beiträge mit dem "Abstimmen"-Button (links) und Beiträge die eine Frage von dir beantwortet haben, als "Antwort" (unten).
    Warum das Ganze? Hier gibts die Antwort.

    Samstag, 5. März 2016 15:06
    Moderator
  • Guten Morgen Jan,

    Nochmals, vielen Dank für die Hilfe.

    Also ich habe das nochmal getestet, leider geht das nicht.

    [xml]$xmlfile = Get-Content C:\XXX\File.xml $xmlfile.UserNotifications.Install.ChildNodes

    Wenn ich, aber

    $xmlfile.UserNotifications.Install

    Dann bekomme ich div. Informationen, aus dem XML File.

    lang              : de-DE
    colorscheme       : blue
    icon              : Blueshield
    showtrayicon      : true
    Caption           : Aktualisierung
    Instruction       : Beenden Sie ZZZ, um die Aktualisierung zu starten.
    Description       : Für die Aktualisierung ist das Schließen von ZZZ erforderlich. Stellen Sie sicher, dass Sie alle Daten gespeichert haben.
    RemindLater       : Später erinnern:
    RemindLaterButton : Später durchführen
    ActionButton      : Installation starten
    SkipText          : Sind Sie sicher, dass Sie die Installation abbrechen wollen?
    AutoCloseText     : Start in: {0} Min, {1} Sek.
    ProcessClose      : XXX
    
    lang              : en-US
    colorscheme       : blue
    icon              : Blueshield
    showtrayicon      : true
    Caption           : Software Update
    Instruction       : Close ZZZ in order to start the update
    Description       : To start the update it is necessary to close ZZZ. Please assure that all data has been saved, if needed.
    RemindLater       : Remind me in:
    RemindLaterButton : Postpone
    ActionButton      : Install now
    SkipText          : Are you sure you want to cancel the installation?
    AutoCloseText     : Starting in: {0} min, {1} sec
    ProcessClose      : XXX

    gebe ich dann die Variable ein

    $xmlfile
    
    xml                                   UserNotifications
    ---                                   -----------------
    version="1.0" encoding="Windows-1252" UserNotifications

    Bekomme ich auch das was Du mir da vorgibst.

    Gruß

    Markus

    Montag, 7. März 2016 07:27
  • Hallo,

    Hab es jetzt hinbekommen.


    $Prozesse = ""
    $Ausgabe = ""
        $CurrentXMLFile = 'C:\File.xml'
        [xml]$xmlfile = Get-Content ($CurrentXMLFile)
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Install[@lang='de-DE']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Install[@lang='en-US']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Uninstall[@lang='de-DE']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
     $delnodes = $xmlfile.SelectSingleNode("//UserNotifications/Uninstall[@lang='en-US']/ProcessClose")
     $delnodes | %{ $_.parentnode.removechild($_) }
    
    $Prozesse="Winword.exe,Notepad.exe,Firefox.exe"
    $Ausgabe=$Prozesse -split ","
    
    foreach ($i in $Ausgabe){
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Install[@lang='de-DE']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Install[@lang='en-US']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Uninstall[@lang='de-DE']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    
            $xmlNode = $xmlfile.SelectSingleNode("UserNotifications/Uninstall[@lang='en-US']")
            $newXmlChild = $xmlNode.AppendChild($xmlfile.CreateElement("ProcessClose"))
            $newXmlChildText = $newXmlChild.AppendChild($xmlfile.CreateTextNode("$i"))
    }
    
        $xmlfile.Save($CurrentXMLFile

    Vielleicht kann man das noch besser umsetzten, da ich aber noch ein newbie bin in PS, hab ich das nicht besser hinbekommen.

    Hallo Jan,
    Danke nochmal für die Unterstützung, da es ein teil der Lösung war.

    Gruss
    Markus

    PS. Vielleicht kann mir ja mal jemand das hier erklären, dies ist sehr nervig, ob wohl hier mehr als 4 Zeichen und weniger als 60.000 Zeichen sind. Daher istd er Text jetzt kurz gefasst vorher waren es knapp 3000 Zeichen mit Code.


    Dienstag, 8. März 2016 10:11