I'm trying to insert 800 unique <REMARK>this is a remark</REMARK>
elements into an existing set of 800 XML files. I generated 800 documents with only the <REMARK>
element I want inserted into each XML. The thought being, I could insert this element into the corresponding XML document, based on a shared filename. For example, I have an XML called WNYC-SCHK-2004-02-20-37540.xml in one folder with only this information in it <REMARK>Think of Spanish classical music and the name Manuel de Falla naturally comes to mind.</REMARK>
And I want to insert the element into a file also named WNYC-SCHK-2004-02-20-37540.xml just below the <CHANGETIME>
element below:
<?xml version="1.0" encoding="ISO-8859-1"?>
<ENTRIES>
<ENTRY>
<NUMBER>622</NUMBER>
<CLASS>Audio</CLASS>
<TITLE>WNYC-SCHK-2004-02-20-37540</TITLE>
<GENERATOR>DBM</GENERATOR>
<CREATOR>JPASSMOR</CREATOR>
<DATE>2015-01-06</DATE>
<DATUM>2015-01-06</DATUM>
<TIME>11:48:59</TIME>
<TIMESTAMP>2015-01-06 11:48:59</TIMESTAMP>
<LENGTH>00:58:53.920</LENGTH>
<DURATION>3533920</DURATION>
<SOFTDELETED>0</SOFTDELETED>
<NODELETE>0</NODELETE>
<READY>0</READY>
<PERFECT>0</PERFECT>
<FORARCHIVE>0</FORARCHIVE>
<ARCHIVING>0</ARCHIVING>
<ARCHIVED>0</ARCHIVED>
<GROWING>0</GROWING>
<NEW>0</NEW>
<INVALID>0</INVALID>
<LOWRESEXISTS>0</LOWRESEXISTS>
<KEYFRAMEEXISTS>0</KEYFRAMEEXISTS>
<VSAT>0</VSAT>
<LOOP>0</LOOP>
<INVISIBLE>0</INVISIBLE>
<SHAREDAUDIO>0</SHAREDAUDIO>
<TRANSMITTED>0</TRANSMITTED>
<ROYALTIES>0</ROYALTIES>
<WITHTEXTFILE>0</WITHTEXTFILE>
<INDEXED>0</INDEXED>
<PERSONALRADIO>0</PERSONALRADIO>
<REQUESTDEARCHIVE>0</REQUESTDEARCHIVE>
<REPLFLAGS>0</REPLFLAGS>
<STATE>Existing</STATE>
<AUTHOR>ARCHIVES</AUTHOR>
<EDITOR>JPASSMOR</EDITOR>
<CHANGEUSER>JPASSMOR</CHANGEUSER>
<CHANGEDATE>2015-01-26</CHANGEDATE>
<CHANGETIME>09:33:07</CHANGETIME>
<FILESIZE>628255824</FILESIZE>
<AUDIOFORMAT>Wave,BWF,RIFF</AUDIOFORMAT>
<AUDIOMODE>Stereo</AUDIOMODE>
<SAMPLERATE>44100</SAMPLERATE>
<BITRATE>0</BITRATE>
<TEXTLENGTH>00:00:00.000</TEXTLENGTH>
<TEXTDURATION>0</TEXTDURATION>
<BROADCASTINGS>0</BROADCASTINGS>
<MARKIN>00:00:00.000</MARKIN>
<MARKOUT>00:58:53.920</MARKOUT>
</ENTRY>
</ENTRIES>
so that it looks like this
<?xml version="1.0" encoding="ISO-8859-1"?>
<ENTRIES>
<ENTRY>
<NUMBER>622</NUMBER>
<CLASS>Audio</CLASS>
<TITLE>WNYC-SCHK-2004-02-20-37540</TITLE>
<GENERATOR>DBM</GENERATOR>
<CREATOR>JPASSMOR</CREATOR>
<DATE>2015-01-06</DATE>
<DATUM>2015-01-06</DATUM>
<TIME>11:48:59</TIME>
<TIMESTAMP>2015-01-06 11:48:59</TIMESTAMP>
<LENGTH>00:58:53.920</LENGTH>
<DURATION>3533920</DURATION>
<SOFTDELETED>0</SOFTDELETED>
<NODELETE>0</NODELETE>
<READY>0</READY>
<PERFECT>0</PERFECT>
<FORARCHIVE>0</FORARCHIVE>
<ARCHIVING>0</ARCHIVING>
<ARCHIVED>0</ARCHIVED>
<GROWING>0</GROWING>
<NEW>0</NEW>
<INVALID>0</INVALID>
<LOWRESEXISTS>0</LOWRESEXISTS>
<KEYFRAMEEXISTS>0</KEYFRAMEEXISTS>
<VSAT>0</VSAT>
<LOOP>0</LOOP>
<INVISIBLE>0</INVISIBLE>
<SHAREDAUDIO>0</SHAREDAUDIO>
<TRANSMITTED>0</TRANSMITTED>
<ROYALTIES>0</ROYALTIES>
<WITHTEXTFILE>0</WITHTEXTFILE>
<INDEXED>0</INDEXED>
<PERSONALRADIO>0</PERSONALRADIO>
<REQUESTDEARCHIVE>0</REQUESTDEARCHIVE>
<REPLFLAGS>0</REPLFLAGS>
<STATE>Existing</STATE>
<AUTHOR>ARCHIVES</AUTHOR>
<EDITOR>JPASSMOR</EDITOR>
<CHANGEUSER>JPASSMOR</CHANGEUSER>
<CHANGEDATE>2015-01-26</CHANGEDATE>
<CHANGETIME>09:33:07</CHANGETIME>
<REMARK>Think of Spanish classical music and the name Manuel de Falla naturally comes to mind.</REMARK>
<FILESIZE>628255824</FILESIZE>
<AUDIOFORMAT>Wave,BWF,RIFF</AUDIOFORMAT>
<AUDIOMODE>Stereo</AUDIOMODE>
<SAMPLERATE>44100</SAMPLERATE>
<BITRATE>0</BITRATE>
<TEXTLENGTH>00:00:00.000</TEXTLENGTH>
<TEXTDURATION>0</TEXTDURATION>
<BROADCASTINGS>0</BROADCASTINGS>
<MARKIN>00:00:00.000</MARKIN>
<MARKOUT>00:58:53.920</MARKOUT>
</ENTRY>
</ENTRIES>
I thought that there might be a way to use xsl to copy the remark from one xml doc into the other based on a shared filename in a batch. Or might there be an easier way to do it?
This problem have an interesting aspect, so I used it to test a different method to process files.
@echo off
setlocal EnableDelayedExpansion
rem Process all .xml files in current directory
for %%a in (*.xml) do (
rem Locate the line numbers where "CHANGETIME" and "/ENTRIES" appears
set "insertLine="
for /F "delims=:" %%b in ('findstr /N "CHANGETIME /ENTRIES" "%%a"') do (
if not defined insertLine (
set "insertLine=%%b"
) else (
set "lastLine=%%b"
)
)
rem Block used to read-input-file/create-output-file
< "%%a" (
rem Read the first line from input file
set /P "line="
rem Copy lines up to the insertion point
for /L %%i in (1,1,!insertLine!) do set /P "line=!line!" & echo/
rem Insert the corresponding REMARK file
type "RemarksFolder\%%a"
rem Copy the rest of lines
set /A insertLine+=1
for /L %%i in (!insertLine!,1,!lastLine!) do set /P "line=!line!" & echo/
) > "output.tmp"
rem Block-end
rem Replace input file with created output file
move /Y "output.tmp" "%%a" > NUL
)
This program should run faster than other methods that compare line by line; however, it has the disadvantage that leading spaces are removed from all lines. Although additional code may be inserted in order to fix this point, doing that will slow down the process...
The batch environment isn't terribly strongly suited for manipulating XML as XML. There's probably a way using Windows Script Host (VBScript or JScript) to evaluate the XML DOM, but in this situation it's probably easier just to use for
loops and echo
s.
Read the remarks in the following example script for a full explanation of how it works.
@echo off
setlocal
set "remarkDir=remarks\"
set "xmlDir=xml\"
rem // for all files in xmlDir\*.xml
for %%I in ("%xmlDir%\*.xml") do (
rem // echo filename without line break...
set /P "=Processing %%~nxI... "<NUL
rem // Read corresponding remark file into variable
set /P "remark=" <"%remarkDir%\%%~nxI"
rem // for each line in xmlDir\file.xml
for /f "usebackq delims=" %%X in ("%%~fI") do (
rem // append the line to a new file
>>"%%~dpnI.new" echo/%%X
rem // check whether the line contains /CHANGETIME
set "line=%%X"
setlocal enabledelayedexpansion
if not "%%X"=="!line:/CHANGETIME=!" (
rem // Line contains /CHANGETIME. Append remark.
>>"%%~dpnI.new" echo/!remark!
)
endlocal
)
rem // End of xml file. Replace old with new.
move /y "%%~dpnI.new" "%%~fI" >NUL
echo Done.
)
note: StackOverflow isn't intended to be a free coding service, but I have sympathy for you. It sounds like you've put a lot of effort into painting yourself into this corner. Therefore, I hope this helps you out.
Excuse me. In my first answer I said I wanted to use this problem as a test because its interesting aspect. Some time ago I wrote FilePointer.exe auxiliary program that allows to move the file pointer of a redirected file via its standard handle. That program may be used to solve this problem in a very simple way (and also any other problem with similar structure) because the former method of copy several lines via FOR command may be changed by a direct file pointer movement to a certain file position, or by a simple FINDSTR command to copy the rest of lines. Here it is:
@echo off
setlocal EnableDelayedExpansion
rem Example of use of FilePointer.exe auxiliary program
rem Antonio Perez Ayala
rem Process all .xml files in current directory
for %%a in (*.xml) do (
rem Locate the insertion offset where "FILESIZE" line starts
for /F "delims=:" %%b in ('findstr /O "FILESIZE" "%%a"') do set "insertPoint=%%b"
rem Block used to edit the file via redirected Stdin and Stdout
< "%%a" (
rem Set Stdin file pointer at the insertion point
FilePointer 0 !insertPoint!
rem Copy the rest of lines to an auxiliary file
findstr "^" > auxiliary.tmp
rem "FIND and MORE works different than FINDSTR."
rem "FIND and MORE first resets the file position variable and then read the complete file to the EOF,"
rem "If you use FINDSTR it simply reads the next data from current position, ..."
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=2128&p=9720#p9720
rem Set Stdout file pointer at the insertion point
FilePointer 1 !insertPoint!
rem Insert the corresponding REMARK file
type "RemarksFolder\%%a"
rem And add the rest of lines
type auxiliary.tmp
) >> "%%a"
rem Block-end
)
del auxiliary.tmp
This method have several advantages over the former one. It run faster and the leading spaces are preserved. The first part of the file is kept in the same file, that is, it does not need to copy it into a temporary file. In this problem it is necessary to copy the lines from the insertion point to the EOF in a temporary file in order to make room for the inserted text, but in another problem that just needs to replace a text by other one of the same size, the change is immediate with no further processing no matter the size of the file! If the new text would be shorter than the original one it would be necessary to "compact" the data after the replacement point and then truncate the remaining data, that may be done with Truncate.exe (another one of my auxiliary programs).
You may download FilePointer.exe auxiliary program from this site.