Inhalt einer XML Datei per Batch bzw. Script ändern
Hallo zusammen,
ich versuche mich schon seit mehreren Tagen an der Lösung untenstehenden Problems komme aber leider nicht weiter. Diverse Versuche aufgrund ähnlicher Threads scheitertern kläglich. Ich hoffe daher auf Eure Hilfe. Bin absoluter Script Novize.
Ich bekomme taeglich mehrere XML Dateien geliefert welche in ein Warenwirtschaftssystem eingelesen werden sollen.
Leider kann ich das WAWI Programm nicht dazu bringen alle für mich wichtigen Inhalte der XML Datei zu verarbeiten. Das gelieferte XML Format lässt sich durch den Lieferer leider nicht ändern. (IPad APP)
Es muss demzufolge der Inhalt der XML in mindestens zwei Bereichen geändert werden damit ich sie komplett verarbeiten kann.
1. Der Inhalt zwischen <arbeiten></arbeiten> in Zeile 11-13 sollte den wert zwischen <arbeitszeitBeginn></arbeitszeitBeginn> in Zeile 50 ersetzen. Die dortigen Werte sind für mich unwichtig, den datensatz kann ich aber dann entsprechend zuordnen. Schön wäre, wenn die Zeilenumbrüche erhalten bleiben, ist aber nicht zwingend.
2. Bei dem Wert zwischen <arbeitszeit></arbeitszeit> in Zeile 49 muß das "h" weg.
3. Ein fester Wert z.B. 1050 sollte den Wert zwischen <arbeitszeitEnde></arbeitszeitEnde> in Zeile 51 ersetzen.
4. Schön wäre, wenn das script alle XML Dateien die in einem bestimmten Verzeichniss liegen entsprechend abarbeitet.
Mit den Zeilennummern kann in dem Script nicht gearbeitet werden da sie variieren.
So sieht die gelieferte XML datei aus:
Ich hoffe es kann mir jemand weiterhelfen.
ich versuche mich schon seit mehreren Tagen an der Lösung untenstehenden Problems komme aber leider nicht weiter. Diverse Versuche aufgrund ähnlicher Threads scheitertern kläglich. Ich hoffe daher auf Eure Hilfe. Bin absoluter Script Novize.
Ich bekomme taeglich mehrere XML Dateien geliefert welche in ein Warenwirtschaftssystem eingelesen werden sollen.
Leider kann ich das WAWI Programm nicht dazu bringen alle für mich wichtigen Inhalte der XML Datei zu verarbeiten. Das gelieferte XML Format lässt sich durch den Lieferer leider nicht ändern. (IPad APP)
Es muss demzufolge der Inhalt der XML in mindestens zwei Bereichen geändert werden damit ich sie komplett verarbeiten kann.
1. Der Inhalt zwischen <arbeiten></arbeiten> in Zeile 11-13 sollte den wert zwischen <arbeitszeitBeginn></arbeitszeitBeginn> in Zeile 50 ersetzen. Die dortigen Werte sind für mich unwichtig, den datensatz kann ich aber dann entsprechend zuordnen. Schön wäre, wenn die Zeilenumbrüche erhalten bleiben, ist aber nicht zwingend.
2. Bei dem Wert zwischen <arbeitszeit></arbeitszeit> in Zeile 49 muß das "h" weg.
3. Ein fester Wert z.B. 1050 sollte den Wert zwischen <arbeitszeitEnde></arbeitszeitEnde> in Zeile 51 ersetzen.
4. Schön wäre, wenn das script alle XML Dateien die in einem bestimmten Verzeichniss liegen entsprechend abarbeitet.
Mit den Zeilennummern kann in dem Script nicht gearbeitet werden da sie variieren.
So sieht die gelieferte XML datei aus:
<?xml version="1.0" encoding="UTF-8"?>
<stundenbericht>
<rechnungsadresse>10101
Testvorname Testnachnme
Teststrasse 11
12345 Testort
Deutschland</rechnungsadresse>
<ausfuehrungsort/>
<berichtNr>14</berichtNr>
<arbeiten>Leistung 1
Leistung 2
Leistung 3</arbeiten>
<material/>
<materialeintrag>
<bezeichnung>Testartikel</bezeichnung>
<artikelnr>12345</artikelnr>
<menge>1</menge>
<verpackungseinheit/>
<einzelpreis/>
<gesamtpreis>0,00</gesamtpreis>
</materialeintrag>
<materialeintrag>
<bezeichnung>Testartikel2</bezeichnung>
<artikelnr>12346</artikelnr>
<menge>1</menge>
<verpackungseinheit/>
<einzelpreis/>
<gesamtpreis>0,00</gesamtpreis>
</materialeintrag>
<materialeintrag>
<bezeichnung>Testartikel3</bezeichnung>
<artikelnr>12347</artikelnr>
<menge>1</menge>
<verpackungseinheit/>
<einzelpreis/>
<gesamtpreis>0,00</gesamtpreis>
</materialeintrag>
<gesamtpreisNetto>0,00</gesamtpreisNetto>
<steuer>0,00</steuer>
<gesamtpreisBrutto>0,00</gesamtpreisBrutto>
<datum>05.08.11</datum>
<taetigkeit>
<datum>05.08.11</datum>
<fahrzeit/>
<fahrzeitAbfahrt/>
<fahrzeitAnkunft/>
<fahrstrecke/>
<arbeitszeit>0,75h</arbeitszeit>
<arbeitszeitBeginn>23:05</arbeitszeitBeginn>
<arbeitszeitEnde>23:50</arbeitszeitEnde>
<pausenzeit/>
<pausenzeitBeginn/>
<pausenzeitEnde/>
<pausenzeit2/>
<pausenzeit2Beginn/>
<pausenzeit2Ende/>
<name/>
</taetigkeit>
<auswahllisteBezeichnung1>Pos</auswahllisteBezeichnung1>
<auswahleintrag1/>
<unterzeichner/>
</stundenbericht>
Ich hoffe es kann mir jemand weiterhelfen.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 171028
Url: https://administrator.de/contentid/171028
Ausgedruckt am: 22.11.2024 um 21:11 Uhr
33 Kommentare
Neuester Kommentar
Hallo twin850,
Deine XML-Datei ist laut Header in der Codierung UTF-8 gespeichert. Solange keine Umlaute (äöüßÄÖÜ) oder andere Zeichen mit einem Code größer 127 in den Daten vorkommen (kannst Du das garantieren?), ließe sich das ganze noch mit Batchscript verarbeiten, die Aufgabe mit Batchscript zu lösen ist aber umständlich. Dazu wäre VBScript viel besser geeignet. Damit lassen sich aber nur Unicode-Dateien in der Codierung UTF-16 Little Endian verarbeiten.
Du solltest zuerstmal klären, ob die iPad-App die Datei auch als UTF-16 LE oder ANSI (Codepage 1252) codieren kann, bevor wir hier Code für die Tonne produzieren.
Gruß
Friemler
Deine XML-Datei ist laut Header in der Codierung UTF-8 gespeichert. Solange keine Umlaute (äöüßÄÖÜ) oder andere Zeichen mit einem Code größer 127 in den Daten vorkommen (kannst Du das garantieren?), ließe sich das ganze noch mit Batchscript verarbeiten, die Aufgabe mit Batchscript zu lösen ist aber umständlich. Dazu wäre VBScript viel besser geeignet. Damit lassen sich aber nur Unicode-Dateien in der Codierung UTF-16 Little Endian verarbeiten.
Du solltest zuerstmal klären, ob die iPad-App die Datei auch als UTF-16 LE oder ANSI (Codepage 1252) codieren kann, bevor wir hier Code für die Tonne produzieren.
Gruß
Friemler
Hallo twin850,
war evtl. missverständlich ausgedrückt: VBScript kann außer Unicode-Dateien natürlich auch ANSI-Dateien (Codepage 1252) korrekt verarbeiten. Die Zeichencodes zwischen 32 (Leerzeichen) und 127 sind sowohl in ASCII, ANSI und UTF-8 gleich.
Warum Du keine Probleme bei Deinen Experimenten hattest, könnte entweder daran liegen, dass die Codierung im Header tatsächlich falsch angegeben ist und das ganze eine ANSI-Datei ist, oder sie wurde in UTF-8 codiert aber ohne Byte Order Mark (BOM) geschrieben. Die BOM wird in die ersten 3 Bytes einer UTF-8-Datei geschrieben, die die Werte EF BB BF (hexadezimal) haben. Das könntest Du mit einem Hex-Editor oder dem Befehl
Gruß
Friemler
war evtl. missverständlich ausgedrückt: VBScript kann außer Unicode-Dateien natürlich auch ANSI-Dateien (Codepage 1252) korrekt verarbeiten. Die Zeichencodes zwischen 32 (Leerzeichen) und 127 sind sowohl in ASCII, ANSI und UTF-8 gleich.
Warum Du keine Probleme bei Deinen Experimenten hattest, könnte entweder daran liegen, dass die Codierung im Header tatsächlich falsch angegeben ist und das ganze eine ANSI-Datei ist, oder sie wurde in UTF-8 codiert aber ohne Byte Order Mark (BOM) geschrieben. Die BOM wird in die ersten 3 Bytes einer UTF-8-Datei geschrieben, die die Werte EF BB BF (hexadezimal) haben. Das könntest Du mit einem Hex-Editor oder dem Befehl
type "NameDerXMLDatei"
prüfen. Wenn die ersten drei Zeichen der ersten Zeile irgendwelche seltsamen Zeichen sind, hat die Datei eine BOM.Gruß
Friemler
Moin twin850,
teste mal folgendes:
Das Script z.B. als Replace.vbs speichern.
Aufruf
Du kannst in Zeile 5 den festen Wert vorgeben, der in Zeile 51 der (Beispiel-)XML-Datei eingefügt werden soll, und das Icon des Verzeichnisses, das die XML-Dateien enthält, per Drag&Drop auf das Icon des Scripts ziehen
oder
das Script folgendermaßen aufrufen
oder
das Script folgendermaßen aufrufen
In diesem Fall wird der Fixwert aus der Befehlszeile verwendet, auch wenn im Scriptcode ein anderer Wert gesetzt ist.
Es wird im selben Verzeichnis, in dem die Eingabedateien liegen, für jede Eingabedatei eine neue Ausgabedatei erzeugt, deren Namen um
Gruß
Friemler
teste mal folgendes:
Const ForReading = 1
Const AsASCII = 0
strFixedValue = "1050"
If WScript.Arguments.Count > 0 Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
strSrcDir = objFSO.GetAbsolutePathName(WScript.Arguments(0))
If WScript.Arguments.Count > 1 Then strFixedValue = WScript.Arguments(1)
If objFSO.FolderExists(strSrcDir) Then
Set objRegExp = New RegExp
objRegExp.Global = False
objRegExp.IgnoreCase = True
For Each objFile In objFSO.GetFolder(strSrcDir).Files
If LCase(objFSO.GetExtensionName(objFile.Name)) = "xml" Then
'Eingabedatei lesen
Set objInFile = objFile.OpenAsTextStream(ForReading, AsASCII)
strContent = objInFile.ReadAll
objInFile.Close
'Den Wert zwischen <arbeitszeitBeginn></arbeitszeitBeginn>
'durch den Wert zwischen <arbeiten></arbeiten> ersetzen
objRegExp.Pattern = "<arbeiten>"
Set colMatch1 = objRegExp.Execute(strContent)
objRegExp.Pattern = "</arbeiten>"
Set colMatch2 = objRegExp.Execute(strContent)
If (colMatch1.Count > 0) And (colMatch2.Count > 0) Then
intKeyValueStart = colMatch1(0).FirstIndex + 1 + colMatch1(0).Length
intKeyValueLen = colMatch2(0).FirstIndex + 1 - intKeyValueStart
strReplace = Mid(strContent, intKeyValueStart, intKeyValueLen)
objRegExp.Pattern = "(<arbeitszeitBeginn>).*(</arbeitszeitBeginn>)"
strContent = objRegExp.Replace(strContent, "$1" & strReplace & "$2")
End If
'Das h bei dem Wert zwischen <arbeitszeit></arbeitszeit> entfernen
objRegExp.Pattern = "(<arbeitszeit>)([0-9,]{1,}).{1,}(</arbeitszeit>)"
strContent = objRegExp.Replace(strContent, "$1$2$3")
'Den Wert zwischen <arbeitszeitEnde></arbeitszeitEnde>
'durch einen fixen Wert ersetzen
objRegExp.Pattern = "(<arbeitszeitEnde>).*(</arbeitszeitEnde>)"
strContent = objRegExp.Replace(strContent, "$1" & strFixedValue & "$2")
'Ausgabedaei schreiben
Set objOutFile = objFSO.CreateTextFile(objFSO.BuildPath(strSrcDir, objFSO.GetBaseName(objFile.Name) & "_Neu." & objFSO.GetExtensionName(objFile.Name)), True)
objOutFile.Write strContent
objOutFile.Close
End If
Next
End If
End If
Das Script z.B. als Replace.vbs speichern.
Aufruf
Du kannst in Zeile 5 den festen Wert vorgeben, der in Zeile 51 der (Beispiel-)XML-Datei eingefügt werden soll, und das Icon des Verzeichnisses, das die XML-Dateien enthält, per Drag&Drop auf das Icon des Scripts ziehen
oder
das Script folgendermaßen aufrufen
cscript /nologo "Replace.vbs" "PfadDesVerzeichnissesMitDenXMLDateien"
oder
das Script folgendermaßen aufrufen
cscript /nologo "Replace.vbs" "PfadDesVerzeichnissesMitDenXMLDateien" "FixerWert"
Es wird im selben Verzeichnis, in dem die Eingabedateien liegen, für jede Eingabedatei eine neue Ausgabedatei erzeugt, deren Namen um
_Neu
ergänzt wurden (aus z.B. Datei.xml
wird Datei_Neu.xml
).Gruß
Friemler
Hallo twin850 und willkommen im Forum, hallo Friemler!
Mit etwas Verspätung (und nur mal zum Testen für eine einzelne Datei) mein (nicht unähnlicher ) Ansatz:
Im Zweifelsfall würde ich nur Quell- und Zieldateinamen als Parameter übernehmen und das Abarbeiten aller Dateien einem Batch überlassen ...
Grüße
bastla
Mit etwas Verspätung (und nur mal zum Testen für eine einzelne Datei) mein (nicht unähnlicher ) Ansatz:
Ein = "D:\Test.xml"
Aus = "D:\Korrigiert.xml"
FestWert = "1050"
Set fso = CreateObject("Scripting.FileSystemObject")
Set rE = New RegExp
T = fso.OpenTextFile(Ein).ReadAll
rE.Pattern = "<arbeiten>([\S\s]+)</arbeiten>"
Set Matches = rE.Execute(T)
If Matches.Count = 0 Then
WScript.Echo "Leistungsdaten nicht gefunden!"
WScript.Quit(1)
End If
Wert = Matches(0).SubMatches(0)
rE.Pattern = "<arbeitszeitBeginn>.*</arbeitszeitBeginn>"
T = rE.Replace(T, "<arbeitszeitBeginn>" & Wert & "</arbeitszeitBeginn>")
rE.Pattern = "(<arbeitszeit>[^h]*)(h)(</arbeitszeit>)"
T = rE.Replace(T, "$1$3")
rE.Pattern = "<arbeitszeitEnde>.*</arbeitszeitEnde>"
T = rE.Replace (T, "<arbeitszeitEnde>" & FestWert & "</arbeitszeitEnde>")
fso.CreateTextFile(Aus).Write T
Grüße
bastla
Hallo Zusammen.
Windows stellt doch extra zur Verarbeitung von XML Dateien ein ActiveX-Object zur Verfügung.
Für eine einzelne XML-Datei namens "test.xml" könnte das ganze dann so aussehen:
Wenn es so funktioniert, ist die Massenverarbeitung aller XML Dateien in einem Verzeichnis nur noch Makulatur.
Grüße
rubberman
<EDIT: bastlas Vorschlag berücksichtigt. />
Windows stellt doch extra zur Verarbeitung von XML Dateien ein ActiveX-Object zur Verfügung.
Für eine einzelne XML-Datei namens "test.xml" könnte das ganze dann so aussehen:
Const strXmlDoc = "test.xml"
Set objXmlDoc = CreateObject("Microsoft.XMLDOM")
objXmlDoc.async = False
objXmlDoc.load(strXmlDoc)
Set objNode1 = objXmlDoc.documentElement.SelectSingleNode("//arbeiten")
If objNode1 Is Nothing Then
MsgBox "Der Knoten ""arbeiten"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
Set objNode2 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitBeginn")
If objNode2 Is Nothing Then
MsgBox "Der Knoten ""arbeitszeitBeginn"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
objNode2.text = objNode1.text
Set objNode3 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeit")
If objNode3 Is Nothing Then
MsgBox "Der Knoten ""arbeitszeit"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
strArbeitszeit = objNode3.text
objNode3.text = Left(strArbeitszeit, Len(strArbeitszeit) - 1)
Set objNode4 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitEnde")
If objNode4 Is Nothing Then
MsgBox "Der Knoten ""arbeitszeitEnde"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
objNode4.text = "1050"
objXmlDoc.save(strXmlDoc)
Set objXmlDoc = Nothing
Grüße
rubberman
<EDIT: bastlas Vorschlag berücksichtigt. />
Hallo bastla,
klar, das macht immer Sinn, so kann man ja voneinander lernen.
Gruß
Friemler
Zitat von @bastla:
so gesehen hatte es dann aber trotzdem etwas Sinn, auch meine Variante anzubieten ...
so gesehen hatte es dann aber trotzdem etwas Sinn, auch meine Variante anzubieten ...
klar, das macht immer Sinn, so kann man ja voneinander lernen.
Gruß
Friemler
Hallo Friemler,
eine Liste mit allen ActiveX Objekten und Ihrer Referenz würde vermutlich den Rahmen sprengen. Letztlich findest du eine solche Liste aber in der Registry.
Schau mal hier. Die Referenzen dazu findest du dann sicher im MSDN.
Grüße
rubberman
eine Liste mit allen ActiveX Objekten und Ihrer Referenz würde vermutlich den Rahmen sprengen. Letztlich findest du eine solche Liste aber in der Registry.
Schau mal hier. Die Referenzen dazu findest du dann sicher im MSDN.
Grüße
rubberman
Hallo twin850!
Du brauchst ja die Version von rubberman nur ein wenig zu ergänzen, etwa so:
und kannst sie dann per Batch wie folgt verwenden:
Anmerkungen:
Beides ungetestet
Wenn's "unattended" laufen soll, die Zeilen der Art
entweder auf
ändern oder durch ein vorangestelltes
Grüße
bastla
[Edit] Gegen Fehler durch automatisches Wiederherstellen der Sicherungskopie zusätzlich abgesichert - ist aber eigentlich unnötig, da ja Änderungen ohnehin nur geschrieben werden, wenn das Script fehlerfrei durchläuft ... [/Edit]
Du brauchst ja die Version von rubberman nur ein wenig zu ergänzen, etwa so:
'XML_bearbeiten
If WScript.Arguments.Count = 0 Then
MsgBox "Keine Datei übergeben!", vbCritical, "Fehler"
WScript.Quit 2
End If
strXmlDoc = WScript.Arguments(0)
Set objXmlDoc = CreateObject("Microsoft.XMLDOM")
objXmlDoc.async = False
objXmlDoc.load(strXmlDoc)
Set objNode1 = objXmlDoc.documentElement.SelectSingleNode("//arbeiten")
If objNode1 Is Nothing Then
MsgBox "Der Knoten ""arbeiten"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
Set objNode2 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitBeginn")
If objNode2 Is Nothing Then
MsgBox "Der Knoten ""arbeitszeitBeginn"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
objNode2.text = objNode1.text
Set objNode3 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeit")
If objNode3 Is Nothing Then
MsgBox "Der Knoten ""arbeitszeit"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
strArbeitszeit = objNode3.text
objNode3.text = Left(strArbeitszeit, Len(strArbeitszeit) - 1)
Set objNode4 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitEnde")
If objNode4 Is Nothing Then
MsgBox "Der Knoten ""arbeitszeitEnde"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Quit 1
End If
objNode4.text = "1050"
objXmlDoc.save(strXmlDoc)
Set objXmlDoc = Nothing
@echo off & setlocal
set "Verzeichnis=D:\XML"
set "Script=D:\XML_bearbeiten.vbs"
set "Fehler=%Verzeichnis%\Fehler.txt"
pushd "%Verzeichnis%"
del "%Fehler%"
for /f "delims=" %%i in ('dir /b /a-d *.xml') do (
copy "%%i" *.bak
echo Bearbeite: %%i
cscript //nologo "Script%" "%%i" || (
move "%%~ni.bak" *.xml
echo Fehler!
>>"%Fehler%" echo %%i
)
echo\
)
if exist "%Fehler%" notepad "%Fehler%"
popd
Beides ungetestet
Wenn's "unattended" laufen soll, die Zeilen der Art
MsgBox "Der Knoten ""arbeitszeitBeginn"" wurde nicht gefunden!", vbCritical, "Fehler"
WScript.Echo "Der Knoten ""arbeitszeitBeginn"" wurde nicht gefunden!"
REM
auskommentieren - die Dateien mit Fehler werden auf jeden Fall in der "Fehler.txt" protokolliert (und in der aktuellen Version auch durch die vorher erstellte Sicherungskopie ersetzt) ...Grüße
bastla
[Edit] Gegen Fehler durch automatisches Wiederherstellen der Sicherungskopie zusätzlich abgesichert - ist aber eigentlich unnötig, da ja Änderungen ohnehin nur geschrieben werden, wenn das Script fehlerfrei durchläuft ... [/Edit]
Hallo twin850, hallo bastla.
Ich würde dann, wie von Friemler vorgeschlagen, die Verarbeitung des Verzeichnisses auch im VBScript vornehmen, da der wiederholte Aufruf des Scripts eine Menge Zeit frisst.
Ungetestet:
Grüße
rubberman
Ich würde dann, wie von Friemler vorgeschlagen, die Verarbeitung des Verzeichnisses auch im VBScript vornehmen, da der wiederholte Aufruf des Scripts eine Menge Zeit frisst.
Ungetestet:
If WScript.Arguments.Count < 1 Then
WScript.Echo "Syntax:" & _
vbLf & "cscript //nologo """ & WScript.ScriptName & """ ""Pfad"" [""FixerWert""]" & _
vbLf & vbLF & "Returncodes:" & _
vbLf & "3 zu wenig Argumente" & _
vbLf & "2 Verzeichnis nicht gefunden" & _
vbLf & "1 eine oder Mehrere Dateien konnten nicht verarbeitet werden" & _
vbLf & "0 alle gefundenen Dateien erfolgreich verarbeitet" & vbLf
WScript.Quit 3
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
strSrcDir = objFSO.GetAbsolutePathName(WScript.Arguments(0))
If Not objFSO.FolderExists(strSrcDir) Then WScript.Quit 2
If WScript.Arguments.Count > 1 Then
strFixedValue = WScript.Arguments(1)
Else
strFixedValue = "1050"
End If
iSucc = 0
iErr = 0
For Each objFile In objFSO.GetFolder(strSrcDir).Files
If LCase(objFSO.GetExtensionName(objFile.Name)) = "xml" Then
If Process_XML(objFile.Path) Then
WScript.Echo """" & objFile.Name & """ - Verarbeitung erfolgreich."
iSucc = iSucc + 1
Else
WScript.Echo """" & objFile.Name & """ - Verarbeitung fehlgeschlagen."
iErr = iErr + 1
End If
End If
Next
WScript.Echo vbLf & iSucc + iErr & " Dateien verarbeitet." & _
vbLf & iSucc & " erfolreich" & _
vbLf & iErr & " fehlgeschlagen" & vbLf
If iErr > 0 Then WScript.Quit 1
Function Process_XML(ByRef strXmlDoc)
Set objXmlDoc = CreateObject("Microsoft.XMLDOM")
objXmlDoc.async = False
objXmlDoc.load(strXmlDoc)
Set objNode1 = objXmlDoc.documentElement.SelectSingleNode("//arbeiten")
If objNode1 Is Nothing Then
Process_XML = False
Exit Function
End If
Set objNode2 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitBeginn")
If objNode2 Is Nothing Then
Process_XML = False
Exit Function
End If
objNode2.text = objNode1.text
Set objNode3 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeit")
If objNode3 Is Nothing Then
Process_XML = False
Exit Function
End If
strArbeitszeit = objNode3.text
objNode3.text = Left(strArbeitszeit, Len(strArbeitszeit) - 1)
Set objNode4 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitEnde")
If objNode4 Is Nothing Then
Process_XML = False
Exit Function
End If
objNode4.text = strFixedValue
objXmlDoc.save(strXmlDoc)
Set objXmlDoc = Nothing
Process_XML = True
End Function
rubberman
Hallo twin850,
habe leider erst nach Feierabend die Zeit gefunden ...
Mit ein paar kleinen Anpassungen sieht das Script nun so aus:
Hoffe das funktioniert wie gewünscht.
Grüße
rubberman
habe leider erst nach Feierabend die Zeit gefunden ...
Mit ein paar kleinen Anpassungen sieht das Script nun so aus:
If WScript.Arguments.Count < 1 Then
WScript.Echo "Syntax:" & _
vbLf & "cscript //nologo """ & WScript.ScriptName & """ ""Pfad"" [""FixerWert""]" & _
vbLf & vbLF & "Returncodes:" & _
vbLf & "3 zu wenig Argumente" & _
vbLf & "2 Verzeichnis nicht gefunden" & _
vbLf & "1 eine oder Mehrere Dateien konnten nicht verarbeitet werden" & _
vbLf & "0 alle gefundenen Dateien erfolgreich verarbeitet" & vbLf
WScript.Quit 3
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
strSrcDir = objFSO.GetAbsolutePathName(WScript.Arguments(0))
If Not objFSO.FolderExists(strSrcDir) Then WScript.Quit 2
If WScript.Arguments.Count > 1 Then
strFixedValue = WScript.Arguments(1)
Else
strFixedValue = "1050"
End If
iSucc = 0
iErr = 0
For Each objFile In objFSO.GetFolder(strSrcDir).Files
If LCase(objFSO.GetExtensionName(objFile.Name)) = "xml" Then
iRet = Process_XML(objFile.Path)
If iRet > 0 Then
WScript.Echo """" & objFile.Name & """ - " & iRet & " Knoten verarbeitet."
iSucc = iSucc + 1
Else
WScript.Echo """" & objFile.Name & """ - Verarbeitung fehlgeschlagen."
iErr = iErr + 1
End If
End If
Next
WScript.Echo vbLf & iSucc + iErr & " Dateien verarbeitet." & _
vbLf & iSucc & " erfolreich" & _
vbLf & iErr & " fehlgeschlagen" & vbLf
If iErr > 0 Then WScript.Quit 1
Function Process_XML(ByRef strXmlDoc)
Set objXmlDoc = CreateObject("Microsoft.XMLDOM")
objXmlDoc.async = False
objXmlDoc.load(strXmlDoc)
iCounter = 0
Set objNode1 = objXmlDoc.documentElement.SelectSingleNode("//arbeiten")
If Not objNode1 Is Nothing Then
Set objNode2 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitBeginn")
If Not objNode2 Is Nothing Then
objNode2.text = objNode1.text
iCounter = iCounter + 2
End If
End If
Set objNode3 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeit")
If Not objNode3 Is Nothing Then
strArbeitszeit = objNode3.text
objNode3.text = Left(strArbeitszeit, Len(strArbeitszeit) - 1)
iCounter = iCounter + 1
End If
Set objNode4 = objXmlDoc.documentElement.SelectSingleNode("//taetigkeit/arbeitszeitEnde")
If Not objNode4 Is Nothing Then
objNode4.text = strFixedValue
iCounter = iCounter + 1
End If
Set objNode5 = objXmlDoc.documentElement.SelectSingleNode("//rechnungsadresse")
If Not objNode5 Is Nothing Then
strrechnungsadresse = objNode5.text
objNode5.text = Left(strrechnungsadresse, 5)
iCounter = iCounter + 1
End If
If iCounter > 0 Then objXmlDoc.save(strXmlDoc)
Set objXmlDoc = Nothing
Process_XML = iCounter
End Function
Grüße
rubberman
Hallo twin850.
Verstehe wie es funktioniert. Ich hatte an so etwas triviales wie eine CSV Datei gedacht. Die meisten Datenbanksysteme sind in der Lage solche sonderzeichengetrennten Werte zu importieren.
Was das Rundungsproblem angeht, teste mal mit
Je nach Locale-Einstellung musst du einmalig nachsehen, ob du tatsächlich einen Dezimalwert bekommst und ob das Dezimaltrennzeichen als Komma kommt. Bei mir funktioniert das so.
Grüße
rubberman
Verstehe wie es funktioniert. Ich hatte an so etwas triviales wie eine CSV Datei gedacht. Die meisten Datenbanksysteme sind in der Lage solche sonderzeichengetrennten Werte zu importieren.
Was das Rundungsproblem angeht, teste mal mit
objNode3.text = CStr(Round(Left(strArbeitszeit, Len(strArbeitszeit) - 1) * 4, 0) / 4)
Grüße
rubberman
Hallo twin850,
Der PAUSE Befehl verhindert das Schließen des Fensters.
Falls der Batch nicht im gleichen Verzeichnis mit dem VBScript liegt, musst du natürlich den gesamten Pfad zu replace.vbs angeben.
Andere Möglichkeit:
du legst eine Verknüpfung an, mit ...
Ziel:
Ausführen in:
Grüße
rubberman
Der PAUSE Befehl verhindert das Schließen des Fensters.
@echo off
cscript //nologo "replace.vbs" "PfadDerXMLDateien"
pause
Andere Möglichkeit:
du legst eine Verknüpfung an, mit ...
Ziel:
%SystemRoot%\System32\cmd.exe /k cscript.exe //nologo "C:\Pfad\zu\Replace.vbs" "C:\Pfad\zu\XMLDateien"
Ausführen in:
%SystemRoot%\System32
Grüße
rubberman
Hallo twin850,
hier noch ein Verbesserungsvorschlag von mir. Ich modifiziere dazu mal das letzte Script von Rubberman, poste hier allerdings nur den ersten Teil, ohne das Unterprogramm ProcessXML, da sich dort nichts geändert hat.
Die Meldungen des Scripts werden in eine Log-Datei geschrieben, die im gleichen Verzeichnis wie das Script angelegt wird. Wenn das Script z.B. "PatchXML.vbs" heißt, wird die Log-Datei unter dem Namen "PatchXML YYYY-MM-DD HH-MM-SS.log" angelegt (der Name enthält also einen Zeitstempel). Wenn das Script seine Arbeit getan hat, erscheint eine Dialogbox, die über das Ergebnis informiert und fragt, ob man sich die Log-Datei anschauen möchte. Nach Klick auf den Button "Ja" wird dann Notepad gestartet und zeigt die Datei an.
Vorteil der Ausgabe der Meldungen in eine Log-Datei: Du kannst jetzt wieder den Ordner mit den XML-Dateien per Drag&Drop auf das Icon des Scripts ziehen, ohne bei jeder bearbeiteten Datei eine Dialogbox mit der Meldung "X Knoten verarbeitet" bzw. "Verarbeitung fehlgeschlagen" weg klicken zu müssen.
Gruß
Friemler
hier noch ein Verbesserungsvorschlag von mir. Ich modifiziere dazu mal das letzte Script von Rubberman, poste hier allerdings nur den ersten Teil, ohne das Unterprogramm ProcessXML, da sich dort nichts geändert hat.
If WScript.Arguments.Count < 1 Then
WScript.Echo "Syntax:" & _
vbLf & """" & WScript.ScriptName & """ ""Pfad"" [""FixerWert""]" & _
vbLf & vbLF & "Returncodes:" & _
vbLf & "3 zu wenig Argumente" & _
vbLf & "2 Verzeichnis nicht gefunden" & _
vbLf & "1 eine oder Mehrere Dateien konnten nicht verarbeitet werden" & _
vbLf & "0 alle gefundenen Dateien erfolgreich verarbeitet" & vbLf
WScript.Quit 3
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
strSrcDir = objFSO.GetAbsolutePathName(WScript.Arguments(0))
If Not objFSO.FolderExists(strSrcDir) Then WScript.Quit 2
If WScript.Arguments.Count > 1 Then
strFixedValue = WScript.Arguments(1)
Else
strFixedValue = "1050"
End If
strLogPath = objFSO.GetParentFolderName(WScript.ScriptFullName)
strLogName = objFSO.GetBaseName(WScript.ScriptName) & " " & _
Year(Now) & "-" & Right("0" & Month(Now), 2) & "-" & Right("0" & Day(Now), 2) & " " & _
Right("0" & Hour(Now), 2) & "-" & Right("0" & Minute(Now), 2) & "-" & Right("0" & Second(Now), 2) & _
".log"
Set objLogFile = objFSO.CreateTextFile(objFSO.BuildPath(strLogPath, strLogName), True)
iSucc = 0
iErr = 0
For Each objFile In objFSO.GetFolder(strSrcDir).Files
If LCase(objFSO.GetExtensionName(objFile.Name)) = "xml" Then
iRet = Process_XML(objFile.Path)
If iRet > 0 Then
objLogFile.WriteLine """" & objFile.Name & """ - " & iRet & " Knoten verarbeitet."
iSucc = iSucc + 1
Else
objLogFile.WriteLine """" & objFile.Name & """ - Verarbeitung fehlgeschlagen."
iErr = iErr + 1
End If
End If
Next
objLogFile.Close
strMessage = iSucc + iErr & " Dateien verarbeitet." & _
vbLf & iSucc & " erfolreich" & _
vbLf & iErr & " fehlgeschlagen" & _
vbLf & _
vbLf & "Möchten Sie sich die Log-Datei anschauen?"
If iErr = 0 Then
cButtons = vbQuestion
Else
cButtons = vbCritical
End If
If MsgBox(strMessage, cButtons + vbYesNo, WScript.ScriptName) = vbYes Then
Set objShell = CreateObject("WScript.Shell")
objShell.Run "notepad.exe """ & objFSO.BuildPath(strLogPath, strLogName) & """"
End If
If iErr > 0 Then WScript.Quit 1
Die Meldungen des Scripts werden in eine Log-Datei geschrieben, die im gleichen Verzeichnis wie das Script angelegt wird. Wenn das Script z.B. "PatchXML.vbs" heißt, wird die Log-Datei unter dem Namen "PatchXML YYYY-MM-DD HH-MM-SS.log" angelegt (der Name enthält also einen Zeitstempel). Wenn das Script seine Arbeit getan hat, erscheint eine Dialogbox, die über das Ergebnis informiert und fragt, ob man sich die Log-Datei anschauen möchte. Nach Klick auf den Button "Ja" wird dann Notepad gestartet und zeigt die Datei an.
Vorteil der Ausgabe der Meldungen in eine Log-Datei: Du kannst jetzt wieder den Ordner mit den XML-Dateien per Drag&Drop auf das Icon des Scripts ziehen, ohne bei jeder bearbeiteten Datei eine Dialogbox mit der Meldung "X Knoten verarbeitet" bzw. "Verarbeitung fehlgeschlagen" weg klicken zu müssen.
Gruß
Friemler
Hallo zusammen,
ich schließe mich mal diesem Thread an da ich eine ähnliche Frage habe und einfach nicht weiter komme.
Wie kann ich in einer XML einige Zeilen zusätzlich per Script hinzufügen?
Soll:
Ist:
Sprich die Zeilen von 11 bis 17 sollen immer nach <Nm Company Name </Nm> hinzugefügt werden. Diese hinzugefügten Zeilen sind fix und müssen nicht angepasst werden.
Die Datei mit dem neuen Inhalt soll als neue Datei im gleichen Verzeichnis mit anderem Namen abgelegt werden.
Wäre super wenn Ihr Eure Ideen mit einbirngen könntet.
Viele Grüße
Steffen
ich schließe mich mal diesem Thread an da ich eine ähnliche Frage habe und einfach nicht weiter komme.
Wie kann ich in einer XML einige Zeilen zusätzlich per Script hinzufügen?
Soll:
<?xml version="1.0" encoding="utf-8" ?>
<Document>
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>20130619001</MsgId>
<CreDtTm>2013-06-19T14:22:08</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>100.00</CtrlSum>
<InitgPty>
<Nm>Company Name</Nm>
<Id>
<OrgId>
<Othr>
<Id>123456789</Id>
</Othr>
</OrgId>
</Id>
</InitgPty>
</GrpHdr>
</CstmrCdtTrfInitn>
</Document>
Ist:
<?xml version="1.0" encoding="utf-8" ?>
<Document>
<CstmrCdtTrfInitn>
<GrpHdr>
<MsgId>20130619001</MsgId>
<CreDtTm>2013-06-19T14:22:08</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<CtrlSum>100.00</CtrlSum>
<InitgPty>
<Nm>Company Name</Nm>
</InitgPty>
</GrpHdr>
</CstmrCdtTrfInitn>
</Document>
Sprich die Zeilen von 11 bis 17 sollen immer nach <Nm Company Name </Nm> hinzugefügt werden. Diese hinzugefügten Zeilen sind fix und müssen nicht angepasst werden.
Die Datei mit dem neuen Inhalt soll als neue Datei im gleichen Verzeichnis mit anderem Namen abgelegt werden.
Wäre super wenn Ihr Eure Ideen mit einbirngen könntet.
Viele Grüße
Steffen
Hallo riatnep, willkommen im Forum.
Magst du vielleicht trotzdem einen neuen Thread erstellen? Dieser ist 2 Jahre alt und deine Frage wird wohl von den allermeisten Helfern nicht mehr wahrgenommen. (Abgesehen davon, dass du fremde Threads nicht für deine Themen nutzen solltest. Das ist eine Frage der "Netiquette".) Natürlich kannst du dann auf diesen Thread verweisen.
Grüße
rubberman
Magst du vielleicht trotzdem einen neuen Thread erstellen? Dieser ist 2 Jahre alt und deine Frage wird wohl von den allermeisten Helfern nicht mehr wahrgenommen. (Abgesehen davon, dass du fremde Threads nicht für deine Themen nutzen solltest. Das ist eine Frage der "Netiquette".) Natürlich kannst du dann auf diesen Thread verweisen.
Grüße
rubberman