hoomer
Goto Top

Batch textzeile einfügen

Guten Tag alle zusammen,

ich habe mal wieder ein Problem das mittels einer Batch-Datei gelöst werden kann/soll/muss.

Es besteht folgende Herausforderung:

Einer bestehenden XML-Datei die in etwa folgende Struktur hat:

<Herkunfts-ID>??</Herkunfts-ID>
<Benutzer>??</Benutzer>
<anrede>??</anrede>
<name>??</name>
<vorname>??</vorname>
<plz>??</plz>
<ort>??</ort>
<land>??</land>
<staatsang>??</staatsang>
<ausweisnr />
<anreise>??</anreise>
<abreise>??</abreise>
<kategorie>??</kategorie>
<Herkunfts-ID>??</Herkunfts-ID>
<Benutzer>??</Benutzer>
..
soll unter der Zeile <ort>??</ort> eine weitere Zeile hinzugefügt werden <str>.</str>

nach meinen bisherigen Bemühungen und etlichen Stunden der Suche in diversen Foren und mittels Google sieht mein bisheriges Skript wie folgt aus

@echo off > new.xml
setLocal EnableDelayedExpansion
set source=quelle.xml
set target=ziel.xml

for /f "tokens=1 delims=" %%a in ('find /n "*ort>" ^< %source%') do (
set /a i=%%a
set /a i-=1
)
for /f "tokens=* delims= " %%a in (%source%) do (
echo %%a >> %target%
set /a n+=1
if !i! equ !n! echo "<str>.</str>" >> %target%
)

Damit wird die Ausgangsdatei ohne Veränderungen in die Zieldatei geschrieben, die gewünschte Veränderung wird nicht durchgeführt.

Ich hoffe das mir jemand verraten kann an welcher Stelle der Fehler liegt bzw. ob ich den völlig falschen Ansatz verfolgt habe.

PS: Die Ausgangsdatei enthält mehrere hundert dieser Einträge und wird täglich generiert - deshalb ist die Lösung über ein Skript notwendig.

Content-Key: 165571

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

Printed on: April 26, 2024 at 03:04 o'clock

Mitglied: 60730
60730 May 03, 2011 at 13:12:41 (UTC)
Goto Top
moin,

ich machs kurz:

  • @echo off in Betaphasenbatcheln, mag ich überhaupt nicht
  • <code> </code> Blöcke aber sehr wohl
  • Die suchfunktion mit batch xml zeile zu füttern, darfst du dann wieder.

btw:
echo %%a >> du weißt schon das das zeichen hinter %a auch in der gepipten Datei landet?

Gruß
btw²
PS: Die Ausgangsdatei enthält mehrere hundert dieser Einträge und wird täglich generiert - deshalb ist die Lösung über ein Skript notwendig.


Nein - denn eine Strasse nach dem Ort ist alles andere als unüblich, der Verseuursacher der die xml erstellt soll das machen
Member: Friemler
Friemler May 03, 2011 at 13:29:52 (UTC)
Goto Top
Hallo hoomer,

folgender Code sollte Dir helfen:
@echo off & setlocal

set "source=quelle.xml"  
set "dest=ziel.xml"  

type NUL > "%dest%"  

(for /f "tokens=1* delims=:" %%a in ('findstr /n "^" "%source%"') do (  
  <NUL set /p "=%%b" & echo.  
  <NUL set /p "=%%b" | find /i "<ort>" > NUL && (<NUL set /p "=<str>.</str>" & echo.)  
)) > "%dest%"  

Die Zieldatei wird in Zeile 6 erstmal geleert.

Das Script ließt die Quelldatei Zeile für Zeile ein und schreibt in Zeile 9 jede eingelesene Zeile in die Zieldatei. Wenn die zuletzt gelesene/geschriebene Zeile den String <ort> enthält (Groß-/Kleinschreibung egal), wird zusätzlich in Zeile 10 noch <str>.</str> in die Zieldatei geschrieben.

In der Quelldatei vorhandene Leerzeilen werden in die Zieldatei übernommen.

Wenn Du noch weitere Fragen bzgl. der Funktionsweise hast, lass hören.

Gruß
Friemler

P.S.
Zeile 6 kann eigentlich auch weggelassen werden, da die Zieldatei sowieso einfach überschrieben wird.

[EDIT]
Script auf bastlas Vorschlag hin geändert (s.u.)
[/EDIT]
Member: bastla
bastla May 03, 2011 at 15:09:53 (UTC)
Goto Top
@Friemler
Nachdem ich vorher nur kurz zum Drüberlesen Zeit hatte, war ich bei der ziemlich gleichen Struktur wie Du gelandet - allerdings hätte ich nicht Deine elegante "delayedExpansion"-Vermeidungs-Strategie verwendet ... face-smile
Noch eine kleine Anmerkung:
Jede, auch die letzte, Zeile hat einen Anfang, aber nicht jede (nämlich gelegentlich die letzte) Zeile auch ein "Ende" - daher würde ich "$" durch "^" ersetzen.

Grüße
bastla
Member: Friemler
Friemler May 03, 2011 at 16:04:30 (UTC)
Goto Top
Hallo bastla,

Zitat von @bastla:
... daher würde ich "$" durch "^" ersetzen.

ist sinnvoll und auch schon erledigt face-smile.

Gruß
Friemler
Member: bastla
bastla May 03, 2011 at 16:24:53 (UTC)
Goto Top
@Friemler
Sorry, hatte vorhin nicht extra auf die Anführungszeichen, die für "^" (nicht aber für $) benötigt werden, hingewiesen ... face-sad

Grüße
bastla
Member: Friemler
Friemler May 03, 2011 at 18:42:47 (UTC)
Goto Top
Hi bastla,

Zitat von @bastla:
hatte vorhin nicht extra auf die Anführungszeichen, die für "^" (nicht aber für $) benötigt werden, hingewiesen ...

das kam mir gerade auch in den Sinn, habe mich deshalb extra noch mal eingeloggt... Trotzdem Danke.

Gruß
Friemler
Member: hoomer
hoomer May 04, 2011 at 07:09:27 (UTC)
Goto Top
Danke. funktioniert gut - auch wenn das Skript von Friemler für ca 100 Datensätze ungefähr 10 Minuten läuft, aber wenn ich das in der Nacht als Task laufen lasse passt das schon.

Vielen dank

Hoomer
Member: bastla
bastla May 04, 2011 at 09:35:43 (UTC)
Goto Top
Hallo hoomer!

Wenn Du nicht so viel Zeit dafür hättest, würde ich eher zu VBS raten - ungetestet:
Ein = "quelle.xml"  
Aus = "ziel.xml"  
Neu = "<str>.</str>"  

Set fso = CreateObject("Scripting.FileSystemObject")  
Set rE = New RegExp
rE.Global = True
rE.Pattern = "(<ort>.*</ort>)"  

T = fso.OpenTextFile(Ein).ReadAll
fso.CreateTextFile(Aus).Write rE.Replace(T, "$1" & vbCrLf & Neu)  
Grüße
bastla
Member: hoomer
hoomer May 04, 2011 at 19:41:50 (UTC)
Goto Top
Also das Skript funktioniert wie gesagt.

Leider hat sich beim Testen herausgestellt das beim Weiterverarbeiten der ziel XML ein Problem mit Sonderzeichen besteht.

Nachdem ich nun wieder gesucht und probiert habe bin ich auf eine Anleitung in diesem Forum gestoßen und habe diese für meine Bedürfnisse angepasst.
Genau darin liegt das Problem )-:

Folgendes müsste noch in die Batch eingebaut werden damit die Sache PERFEKT funktioniert.

Es sind Doppelpunkte : und Kommas , enthalten die jeweils durch Punkte . ersetzt werden müssten.

Gemäß der gefundenen Anleitung habe ich folgendes konstuiert: (interessant sind nur die ersten 8 Zeilen - da der Rest funktioniert wenn ich Buchstaben statt Sonderzeichen ersetzen möchte)

@echo off
set "von=^^:"   
set "zu=^^."  
:zur Kontrolle ob Variablen i.O. sind
echo %von%
echo %zu%
PAUSE
call :FncReplaseString "%von%" "%zu%" "c:\temp\test.txt"  
goto :EOF

:FncReplaseString  {{comment_single_line_remark:0}}
::Parameters:   <FromString> <ToString> <FileName>
::        or:   <VarNameToReturnReplasedText> <FromString> <ToString> <TextToReplase>
::Note:         "="-Characters are not allowed in FromString 
::Example:      call :FncReplaseString _Var "foo" "bar" "the foo"     (_Var="the bar") 
::              call :FncReplaseString "foo" "bar" "d:\text.txt"      (replase string in text-File) 
  setlocal DisableDelayedExpansion &::damit bei der Wertzuweisung keine Ausrufezeichen verloren gehen
  if "%~4" == "" goto :LEB_FncReplaseString_File  
  ::String im uebergebenen Text austauschen und der Variablen (%1) zuweisen
    set "_FncReplaseString_Text=%~4"  
    setlocal EnableDelayedExpansion  &::ermoeglicht die folgende Syntax
    set _FncReplaseString_Text=!_FncReplaseString_Text:%~2=%~3!
      rem Alternativ dazu: call set %~1=%%_FncReplaseString_Text:%~2=%~3%%
    ::die beiden oben und hier geoeffneten setlocal-Instanzen schließen & Variable uebernehmen:
    endlocal & set "_FncReplaseString_Text=%_FncReplaseString_Text%"  
    endlocal & set "%~1=%_FncReplaseString_Text%"  
   exit /b 0
   
  :LEB_FncReplaseString_File
  set _FncReplaseString_TmpFile=%TMP%\%~n0_out%RANDOM%.tmp
  if exist "%~3" ( ::String in einer Text-Datei austauschen  
    for /F "tokens=1* delims=:" %%a in ('type %3 ^| findstr /n $') do (  
    ::type konvertiert UC nach ANSI; findstr verhindert, dass Leerzeilen verloren gehen
      if not "%%b" == "" (  
        set _FncReplaseString_TextLine=%%b
        setlocal EnableDelayedExpansion  &::ermoeglicht die folgende Syntax
        set _FncReplaseString_TextLine=!_FncReplaseString_TextLine:%~1=%~2!
        echo.!_FncReplaseString_TextLine!
        endlocal &rem schließt die hier geoeffnete setlocal-Instanz
      ) else (echo.)
    ) >>%_FncReplaseString_TmpFile%
    move %_FncReplaseString_TmpFile% "%~3"  
  )
  endlocal &rem schließt die oben geoeffnete setlocal-Instanz
 exit /b 0
PS: Vielen dank an den Verfasser dieser Anleitung - die Kommentare sind durchaus hilfreich.

Danke Hoomer
[Edit] Codeformatierung - sorry @bastla, da bin ich zu ungeduldig zum Warten auf hoomer [/Edit]
Member: bastla
bastla May 04, 2011 at 19:50:14 (UTC)
Goto Top
Hallo hoomer!

Soferne VBS doch eine Option sein sollte, müsste nur die Zeile 10 durch
T = Replace(Replace(fso.OpenTextFile(Ein).ReadAll, ":", "."), ",", ".")
ersetzt werden.

Grüße
bastla

P.S.: Egal, ob CMD oder VBS - mit ""-Formatierung (lässt sich auch nachträglich noch einfügen face-wink) wird's besser lesbar ...
Member: Friemler
Friemler May 04, 2011 at 20:16:51 (UTC)
Goto Top
Hallo Hoomer,

freut mich, dass ich Dir helfen konnte.

Allerdings kommen mir 10 Minuten für 100 Datensätze sehr lange vor. Auf meinem System (Intel Core i5 Quadcore-CPU auf 2,8 GHz, 4GB RAM, Windows 7 Ultimate 32Bit) sind 200 Datensätze in 37 Sekunden verarbeitet. Ihr scheint ja einen ziemlich alten Rechner in Eurem Hotel zu haben face-wink.

Du solltest deshalb evtl. bastlas Rat befolgen, und ein VBScript verwenden. Da wäre die Ersetzung von Doppelpunkten und Kommas auch viel einfacher (und schneller). Ich erweitere hier mal bastlas Code:

Ein = "quelle.xml"  
Aus = "ziel.xml"  
Neu = "<str>.</str>"  

Set fso = CreateObject("Scripting.FileSystemObject")  
Set rE = New RegExp
rE.Global = True
rE.Pattern = "(<ort>.*</ort>)"  

T = fso.OpenTextFile(Ein).ReadAll
T = rE.Replace(T, "$1" & vbCrLf & Neu)  

rE.Pattern = ":|,"  
T = rE.Replace(T, ".")  

fso.CreateTextFile(Aus).Write T

Dann sind meine 200 Test-Datensätze in ca. 0,5 Sekunden verarbeitet.

Gruß
Friemler


[EDIT]
Oh, da war der bastla wieder schneller!
[/EDIT]
Member: bastla
bastla May 04, 2011 at 20:31:44 (UTC)
Goto Top
@Friemler
Oh, da war der bastla wieder schneller!
Dafür hast Du aber die wesentlich übersichtlichere Version geliefert ... face-smile

Grüße
bastla
Member: hoomer
hoomer May 05, 2011 at 12:34:47 (UTC)
Goto Top
Das VB-Skript funktioniert "nur" zum ersetzen der Zeichen.
Ich lasse jetzt erst die Batch durchlaufen und rufe am Ende das VBS auf.

Nicht Elegant aber es funktioniert (-:

nochmals vielen dank

Hoomer
Member: bastla
bastla May 05, 2011 at 13:08:06 (UTC)
Goto Top
Hallo hoomer!

Woran ist das "Nicht-Funktionieren" des VB-Scripts denn zu erkennen?

Grüße
bastla
Member: Friemler
Friemler May 05, 2011 at 13:11:07 (UTC)
Goto Top
Hallo Hoomer,

also bei mir macht das Script beides, die Zeile <str>.</str> einfügen und Doppelpunkte und Kommas ersetzen. Dass das Einfügen der Zeile mit der Straße bei Dir nicht funktioniert, könnte daran liegen, dass in Deiner XML-Datei die Zeile mit dem Ort sich in der Groß-/Kleinschreibung von <ort>xxx</ort> unterscheidet. In dem Fall müsstest Du nach rE.Global = True in Zeile 7 als neue Zeile 8 rE.IgnoreCase = True einfügen.

Gruß
Friemler


[EDIT]
Um Fehler beim Abtippen bzw. Copy&Paste-Fehler zu vermeiden, kannst Du auf das Wort Quelltext am rechten oberen Rand der Box mit dem Script klicken. Der Code erscheint dann in einem neuen Fenster. In dieses Fenster klicken und CTRL+A drücken, dann wird alles selektiert. Dann CTRL+C und Du hast den Quelltext in der Zwischenablage. Dann kannst Du ihn im Fenster eines Texteditors mit CTRL+V einfügen und als VBS-Datei speichern.
[/EDIT]