XML auslesen

  • Hey,

    bin neu hier im Forum und weiß noch nicht genau wo das hier rein gehört.
    Ich benutze autiit erst seit kurzem und würde nun gerne eine XML-Datei einlesen, um z.B. den inhalt als Variablen weiter zu verwenden.

    Meine XML-Datei sieht so aus:

    Nun möchte ich diese XML Datei einlesen und die Werte als Pfade bestimmen, denn ich benutze z.B. den Arbeitspfad /Kunde1/12345/Images, da ich aber mehrere Kunden habe und auch diese Mehrere Objekte wollte ich es in Form eine XML Datei einlesen, da das ganze später automatisiert laufen soll.
    Normales einlesen aus Textdateien ist ja kein Problem für mich nur ich habe schwierigkeiten das er jeden Wert einzelnt als Variable speichern soll und am ende Sozusagen den Pfad "hochzählen" soll, sodass er den nächsten Pfad nimmt und die Prozedur wiederholt.

    Ich hoffe das alles ist nicht zu verwirrend und jemand wüsste vielleicht einen ansatz.
    Für Fragen stehe ich gern zur Verfügung
    MfG
    Toto2468

  • Also im Endeffekt habe ich mit autoit ein Script geschrieben, welches eine AVS datei schreibt (AVISynth), da ich für verschiedene Objekte mehrere Bilder zu einem Video zusammenfügen will.
    Derzeit habe ich das Problem mit einer .txt-Datei und Stringsplit gelößt, jedoch ist es mit einer XML schöner und man hat mehr möglichkeiten zum aufbau.
    Wie gesagt ich möchte die Inhalte der XML als Pfad haben, sodass ich zb Kunde1/12345 als pfand aus der XML anhand von zwei einträgen zusammen bauen kann, da ich viele Verschiedene Kunden mit jeweils mehreren Objekten habe, und da diese sich immer je nach Objektnummer ändern brauche ich hier eine XML (oder zurzeit txt) Datei die ich auslesen kann, um zu wissen welche Objekte neu sind und verarbeitet werden müssen (die XML bzw TXT datei erstelle ich derzeit händisch)

  • Oder könnte mir wenigstens jemand ein Beispiel zum einlesen einer XML Datei geben? Ich habe eine XML Datei wo immer

    <video>
    <Kunde>Klaus</kunde>
    <Objektnummer>12345</Objektnummer>
    <Objektnummer>54815</Objektnummer>
    </video>
    <video>
    <Kunde>Peter</kunde>
    <Objektnummer>45678</Objektnummer>
    </video>

    vorkommt, also Pro kunde können mehrere Objektnummern vorkommen.
    Nun möchte ich die XML so einlesen, das ich die Objektnummer und den Kundenname in eine Variable speichere sodass ich z.B. ein Pfad aus /klaus/12345/ und /klaus/54815/ generieren kann, den in diesem Pfad sind immer Pro Objekt jedes Kunden Bilder hinterlegt, welche weiter verarbeitet werden sollen, da diese Pfade automatisch angelegt werden je nachdem Welches Objekt der Kunde hat, benötige ich hier den automatismus das die XML immer ausgelesen wird und er mir die neuen Pfade generiert.
    Ich hoffe das war einigermaßen verständlich
    Danke für die Hilfe

    MfG
    Toto2468

  • Hi,
    ich verstehe ehrlich gesagt dein Problem nicht...
    Du kannst doch einfach die XML-Datei einlesen und nach den Kunden und Objektnummern splitten. Das funktioniert doch genauso wie mit der txt-Datei.
    Die Kunden und Objektnummern stehen doch dann in Variablen und müssen nur noch zusammengefügt werden.

    Ggf. erstellst du eine Datei mit den "alten" Pfaden und gleichst diese einfach mit der XML-Datei ab, um die "neuen" rauszufiltern.

    Ich kapiere auch nicht, wie bzw. wieso du die XML-Datei "händisch" erstellst? Um sie dann "automatisiert" per Script auszulesen? Das hört sich alles ziemlich krude an, beschreibe doch mal, woher die Kunden und Objektnummern kommen, und wer die Dateipfade mit den neuen Daten anlegt (du schreibst, das ginge "automatisch").

    Zeig doch mal deinen bisherigen Code, damit man sehen kann, wo du Probleme hast.

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (27. September 2013 um 12:45)

  • Hier mal eine simple Variante, das Ganze mit _StringBetween() ohne XML Wrapper zu lösen.
    Am Ende wird ein Array of Arrays mit den einzelnen Pfaden des jeweiligen Kunden erstellt.

    Spoiler anzeigen
    [autoit]

    #include <array.au3>
    #include <String.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $sXML = '<video>' & @CRLF & _
    '<Kunde>Klaus</kunde>' & @CRLF & _
    '<Objektnummer>12345</Objektnummer>' & @CRLF & _
    '<Objektnummer>54815</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Fritz</kunde>' & @CRLF & _
    '<Objektnummer>5677879</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Heinz</kunde>' & @CRLF & _
    '<Objektnummer>43567</Objektnummer>' & @CRLF & _
    '<Objektnummer>87234</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Peter</kunde>' & @CRLF & _
    '<Objektnummer>45678</Objektnummer>' & @CRLF & _
    '</video>'

    [/autoit] [autoit][/autoit] [autoit]

    $aResult = StringRegExp($sXML, "<video>(?s)(.*?)</video>", 3, 1)
    ;_ArrayDisplay($aResult)

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aCustomers[1]

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($aResult) - 1
    Dim $aCustomer[1]
    Dim $aPaths[1]
    $aCustomer = _StringBetween($aResult[$i], "<kunde>", "</kunde>")
    $aObjects = _StringBetween($aResult[$i], "<Objektnummer>", "</Objektnummer>")
    _ArrayConcatenate($aCustomer, $aObjects)
    ;_ArrayDisplay($aCustomer)
    For $j = 1 To UBound($aCustomer) - 1
    _ArrayAdd($aPaths, "/" & $aCustomer[0] & "/" & $aCustomer[$j])
    Next
    ;_ArrayDisplay($aPaths)
    ReDim $aCustomers[UBound($aCustomers) + 1]
    $aCustomers[UBound($aCustomers) - 1] = $aPaths
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To UBound($aCustomers) - 1
    _ArrayDisplay($aCustomers[$i])
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit]
  • So ähnlich sieht meine Lösung mit Regular Expressions auch aus, ich wollte nur eigentlich noch auf ein Skript von ihm warten.

    Spoiler anzeigen
    [autoit]

    Local $sData = ClipGet() ; !!!
    Local $asVideos, $i, $sKunde, $asObjektnummern, $j

    [/autoit] [autoit][/autoit] [autoit]

    $asVideos = StringRegExp($sData, "(?i)(?s)<Video>(.+?)</Video>", 3)
    If @error Then Exit 1

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($asVideos)-1
    $sKunde = StringRegExp($asVideos[$i], "(?i)<Kunde>(.+?)</Kunde>", 3)
    If @error Then Exit 2
    $sKunde = $sKunde[0]
    $asObjektnummern = StringRegExp($asVideos[$i], "(?i)<Objektnummer>(.+?)</Objektnummer>", 3)
    If @error Then Exit 3
    For $j = 0 To UBound($asObjektnummern)-1
    ConsoleWrite("/" & $sKunde & "/" & $asObjektnummern[$j] & "/" & @CRLF)
    Next
    Next

    [/autoit]
  • Vielleicht ist es für den weiteren Programmablauf sinnvoller, in der ersten Spalte des resultierenden Arrays den Namen des jeweiligen Kunden und in der Zweiten das dazugehörige Array mit dn Pfaden abzulegen. So kann man später auf die Pfade eines spezifischen Kunden über ein ArraySearch in der ersten Spalte zugreifen.

    Spoiler anzeigen
    [autoit]

    #include <array.au3>
    #include <String.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $sXML = '<video>' & @CRLF & _
    '<Kunde>Klaus</kunde>' & @CRLF & _
    '<Objektnummer>12345</Objektnummer>' & @CRLF & _
    '<Objektnummer>54815</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Fritz</kunde>' & @CRLF & _
    '<Objektnummer>5677879</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Heinz</kunde>' & @CRLF & _
    '<Objektnummer>43567</Objektnummer>' & @CRLF & _
    '<Objektnummer>87234</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Peter</kunde>' & @CRLF & _
    '<Objektnummer>45678</Objektnummer>' & @CRLF & _
    '</video>'

    [/autoit] [autoit][/autoit] [autoit]

    $aResult = StringRegExp($sXML, "<video>(?s)(.*?)</video>", 3, 1)
    ;_ArrayDisplay($aResult)

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aCustomers[1][2]

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($aResult) - 1
    Dim $aCustomer[1]
    Dim $aPaths[1]
    $aCustomer = _StringBetween($aResult[$i], "<kunde>", "</kunde>")
    ReDim $aCustomers[UBound($aCustomers) + 1][2]
    $aCustomers[UBound($aCustomers) - 1][0] = $aCustomer[0]
    $aObjects = _StringBetween($aResult[$i], "<Objektnummer>", "</Objektnummer>")
    _ArrayConcatenate($aCustomer, $aObjects)
    ;_ArrayDisplay($aCustomer)
    For $j = 1 To UBound($aCustomer) - 1
    _ArrayAdd($aPaths, "/" & $aCustomer[0] & "/" & $aCustomer[$j])
    Next
    ;_ArrayDisplay($aPaths)
    $aCustomers[UBound($aCustomers) - 1][1] = $aPaths
    Next

    [/autoit] [autoit][/autoit] [autoit]

    _ArrayDisplay($aCustomers)
    For $i = 1 To UBound($aCustomers) - 1
    _ArrayDisplay($aCustomers[$i][1])
    Next

    [/autoit]
  • naja, wie gesagt, soweit ja kein Problem...
    Was mich stört ist

    Zitat

    da ich aber mehrere Kunden habe und auch diese Mehrere Objekte wollte ich es in Form eine XML Datei einlesen, da das ganze später automatisiert laufen soll.

    in der Kombination mit

    Zitat

    Also im Endeffekt habe ich mit autoit ein Script geschrieben, welches eine AVS datei schreibt (AVISynth), da ich für verschiedene Objekte mehrere Bilder zu einem Video zusammenfügen will.
    ...SNIP... brauche ich hier eine XML (oder zurzeit txt) Datei die ich auslesen kann, um zu wissen welche Objekte neu sind und verarbeitet werden müssen (die XML bzw TXT datei erstelle ich derzeit händisch)


    Problem ist das Zusammenstellen einiger Bilder, welche an AVISynth übergeben werden sollen.
    Was das alles mit "händisch" erstellten *.txt oder *.xml-Files zu tun hat, da blicke ich nun überhaupt nicht durch.

    Wenn ich für einen Kunden ein Video aus Bildern erstellen will, dann schreibe ich ein Script. Mit diesem wähle ich den Kunden aus einer Liste aus, wähle aus einer zweiten Liste die dem Kunden zugeordneten Bilder (alt/neu), klicke auf "Video erstellen" und AVISynth erstellt das Video anhand der übergebenen Daten und spielt es in meiner GUI ab.
    Bestimmt erstelle ich KEINE Dateien händisch, damit ich mit einem Script diese Dateien auslesen kann um dann ein Video zu bekommen!

  • Hoffen wir, das sich dieses Mysterium mit dem nächsten Erscheinen des TS löst. Wirklich verstehen kann ich dises vorgehen auch nicht. Ich hoffe nur, das es einen Sinn ergibt, der sich uns bislang nicht erschliesst.

    Der TS hat jetzt auf jeden Fall erstmal einen bzw. zwei Ansätze, seine XML auszulesen. Der Rest ergibt sich .... hoffentlich.

  • Hier ein Beispiel noch mit xPath:

    Spoiler anzeigen
    [autoit]

    ; create object
    $xml = ObjCreate("Msxml2.DOMDocument")

    [/autoit] [autoit][/autoit] [autoit]

    If IsObj($xml) Then
    $xml.load('C:\Users\Norman\Desktop\text.xml')
    $xml.setProperty("SelectionLanguage","XPath")

    [/autoit] [autoit][/autoit] [autoit]

    $path="//data/video";
    $nodes = $xml.selectNodes($path)

    [/autoit] [autoit][/autoit] [autoit]

    Local $i=0
    While $i<$nodes.length

    [/autoit] [autoit][/autoit] [autoit]

    Local $j=0
    While $j<$nodes($i).childNodes.length
    ConsoleWrite($nodes($i).childNodes($j).childNodes(0).nodeValue & @CRLF)
    $j += 1
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    $i += 1
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Else
    MsgBox(0,"","error")
    EndIf

    [/autoit]

    Aufbau meiner XML Datei ( ungefähr so wie deine :(

    Spoiler anzeigen

    Der Link zu dem XML Parser ist leider nicht mehr verwendbar, da fehlt irgendwie die hälfte, also einfach das benutzen was ich benutz hab.

    Gruß Greek

  • Danke erstmal für die Antworten!

    Also ich versuche nochmal mein Vorhaben zu erklären:

    Ich möchte mit dem Autoit script eine Avisynth Datei automatisch erzeugen.
    Mir liegt eine XML Datei vor, in der Kundendaten (wie beschrieben, Kunden und Objekte) drin sind. Diese generiert ein Kollege über eine Datenbank, somit weiß ich nie, wie viele einträge die XML haben wird und wie viele Objekte die einzelnen Kunden haben, somit muss ich die XML immer neu auslesen können.
    Die werte der XML datei sollen zu meinem Pfad werden, welchen ich mittels des selben Scripts anlegen möchte. Zurzeit arbeite ich mit txt files welche ich mit stringsplit verarbeite, diese txt files muss ich aber selbst erstellen, da mein kollege produktiv nur XML files erzeugen kann.

    zurzeit beziehe ich mein Pfad immer aus dem Stringsplit und dann beziehe ich daraus mein Pfad:

    [autoit]


    $Txtfile = FileOpen('video.txt', 0)

    [/autoit][autoit][/autoit][autoit]

    $Txtarray = StringSplit(FileReadLine($Txtfile), ";")

    [/autoit][autoit][/autoit][autoit]

    $folder = "Videos" & $Txtarray[$arrayZahlVideo] & ""
    $arrayZahlVideo=$arrayZahlVideo+1
    $folder=$folder & $Txtarray[$arrayZahlVideo] &"\Images"

    [/autoit]


    somit baut mir Autoit den Pfad $folder aus dem ersten Teil des arrays und dem zweiten zusammen (in meiner txt file wäre dies "peter;12345" somit ist nun in der Variable $folder "Videos\peter\12345\Images"

    Da ich diese txt files nicht händisch erstellen möchte sondern die XML Datei von meinem Kollegen nutzen möchte, benötige ich eine möglichkeit die XML Datei auszulesen und daraus meine Pfade automatisch zu generieren um damit zu arbeiten.

    Ich hoffe dies war einigermaßen verständlich geschrieben.

    MfG
    Toto2468

  • Tut mir leid für die vielleicht blöde frage, aber wie lese die XML datei ein sodass er mit arbeiten kann?
    In der einen Version steht der Inhalt der XML ja fest im script, über "FIleOpen" öffnet er meine XML nicht

  • Ah okay mit FileRead geht es nun, das Array gibt er mir nun auch aus.
    Wie kann ich nun die Anzahl meiner Objekte insgesamt zählen? Da ich eine while schleife habe, welche solange läuft, wie Objekte da sind

    Anbei der Autoit script, wo ich eine BAT datei erstelle, genau wie ich zuvor die Avisynth datei erstellt habe mit der selben txt datei und stringsplit.

    [autoit]


    #include <File.au3>
    #include <Array.au3>
    #include <String.au3>

    [/autoit][autoit][/autoit][autoit]

    $BatFileInfoVideo = FileOpen('video.txt', 0)
    $BatFileInfoVideoArray = StringSplit(FileReadLine($BatFileInfoVideo), ";")
    $BatarrayZahlVideo = 1
    $BatarrayZahlVideoAll=UBound($BatFileInfoVideoArray)
    $BatarrayZahlVideoAll=$BatarrayZahlVideoAll-1
    $BatFile = FileOpen('avsmp4.bat', 2)

    [/autoit][autoit][/autoit][autoit]

    FileWrite($BatFile,'@echo on' & @CRLF)

    [/autoit][autoit][/autoit][autoit]

    while $BatarrayZahlVideo <= $BatarrayZahlVideoAll

    [/autoit][autoit][/autoit][autoit]

    $Batfolder = "Videos" & $BatFileInfoVideoArray[$BatarrayZahlVideo] & ""
    $BatarrayZahlVideo=$BatarrayZahlVideo+1
    $Batfolder=$Batfolder & $BatFileInfoVideoArray[$BatarrayZahlVideo] &""

    [/autoit][autoit][/autoit][autoit][/autoit][autoit][/autoit][autoit]

    FileWrite($BatFile,' ' & @CRLF)
    FileWrite($BatFile,'for %%a in ("' & $Batfolder & '*.avs") do ffmpeg -i "%%a" -c:v libx264 -tune Film -crf 28 -preset Fast "' & $Batfolder & '%%~na.mp4"' & @CRLF)

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    $BatarrayZahlVideo=$BatarrayZahlVideo+1

    [/autoit][autoit][/autoit][autoit]

    WEnd

    [/autoit][autoit][/autoit][autoit]

    FileWrite($BatFile,' ' & @CRLF)

    [/autoit]

    Hier möchte ich nun die Lösung von i2c einbauen mit einer XML Datei die Pfade zu bestimmen, leider scheitere ich schon an meiner while schleife, wo ich die menge der Objekte wissen muss.

  • While-Schleife brauchst du in diesem Fall keine, For wäre besser.
    Die Schleife geht dann von 0 bis UBound($Array)-1.

    Edit:
    Mir fällt gerade auf, dass das in meiner Lösung schon so enthalten ist.

    AutoIt Version (Prod): 3.3.14.2

    AutoIt Version (Beta): 3.3.9.5

    ausgewählte Skripte: Chatbot, komplexe Zahlen (UDF)

    Einmal editiert, zuletzt von James (30. September 2013 um 21:32)

  • Spoiler anzeigen
    [autoit]

    #include <array.au3>
    #include <String.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $sXML = '<video>' & @CRLF & _
    '<Kunde>Klaus</kunde>' & @CRLF & _
    '<Objektnummer>12345</Objektnummer>' & @CRLF & _
    '<Objektnummer>54815</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Fritz</kunde>' & @CRLF & _
    '<Objektnummer>5677879</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Heinz</kunde>' & @CRLF & _
    '<Objektnummer>43567</Objektnummer>' & @CRLF & _
    '<Objektnummer>87234</Objektnummer>' & @CRLF & _
    '</video>' & @CRLF & _
    '<video>' & @CRLF & _
    '<Kunde>Peter</kunde>' & @CRLF & _
    '<Objektnummer>45678</Objektnummer>' & @CRLF & _
    '</video>'

    [/autoit] [autoit][/autoit] [autoit]

    $aResult = StringRegExp($sXML, "<video>(?s)(.*?)</video>", 3, 1)
    ;_ArrayDisplay($aResult)

    [/autoit] [autoit][/autoit] [autoit]

    Dim $aCustomers[1][2]

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($aResult) - 1
    Dim $aCustomer[1]
    Dim $aPaths[1]
    $aCustomer = _StringBetween($aResult[$i], "<kunde>", "</kunde>")
    ReDim $aCustomers[UBound($aCustomers) + 1][2]
    $aCustomers[UBound($aCustomers) - 1][0] = $aCustomer[0]
    $aObjects = _StringBetween($aResult[$i], "<Objektnummer>", "</Objektnummer>")
    _ArrayConcatenate($aCustomer, $aObjects)
    ;_ArrayDisplay($aCustomer)
    For $j = 1 To UBound($aCustomer) - 1
    _ArrayAdd($aPaths, "/" & $aCustomer[0] & "/" & $aCustomer[$j])
    Next
    ;_ArrayDisplay($aPaths)
    $aCustomers[UBound($aCustomers) - 1][1] = $aPaths
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 To UBound($aCustomers) - 1 ;durchläuft das Array von Index 1 bis Ende
    $aTmp = $aCustomers[$i][1] ;schreibt das Array aus der Zweiten Dimension (Pfade des Kunden) am aktuellen Index in ein temporäres Array
    For $j = 1 To UBound($aTmp) - 1 ;durchläuft das temporäre Array von Index 1 bis Ende
    MsgBox(0, "", "Mach was mit " & $aTmp[$j]) ;Zugriff auf die einzelnen Pfade des Kunden
    Next
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit]