I have this script, to read xml file. The file contains coordinates and I want to list the coordinates:
@echo off
setlocal EnableDelayedExpansion
FOR %%K IN (*.xml) DO (
SET K=%%K
SET K=!K:~0,-4!
SET "prep=0"
REM READ DATA
FOR /F "tokens=*" %%X IN (!K!.kml) DO (
if !prep! == 1 (
echo %%X
pause
FOR /F %%L IN ("%%X") DO (
SET L=%%L
IF NOT "!L:~0,1!" == "<" (
echo %%L
)
)
SET "prep=0"
)
if "%%X" == "<coordinates>" ( SET "prep=1" )
)
)
I got these result:
14.63778004128814,49.50141683426452,0 14.63696238385996,49.48348965654706,0 14.6
8840586504191,49.47901033971912,0 14.68589371304878,49.49939179836829,0 14.63778
004128814,49.50141683426452,0 </coordinates>
Press and key to continue...
14.63778004128814,49.50141683426452,0
Press and key to continue...
First you see the line with coordinates. Second, in the 3rd loop, there are coordinates printed. But I have only one pair of coordinates printed… If I will press a key again, the batch finishes without printing next columns. Can you help?
Edit
After the answer has been posted, I have question 1) could we use this:
SET LF=^
setlocal EnableDelayedExpansion
... (next code) ...
set "var=!var: =%LF%!"
So when there is no delayed LF variable, we could embed it. Or not?
And 2) why in your code
for %%L in ("!LF!") do set "X=!X: =%%~L!"
Did you use %%~L and not just %%L
Your immediate problem is that FOR /F does not iterate the tokens in a line. It simply parses each token that you ask for. If you don’t specify a “tokens” option, then it defaults to “tokens=1” – it only parses the first token in the line.
However, FOR /F will treat a string as multiple lines if the string contains linefeed characters. It will then iterate each line like you want. The trick is to replace your space delimiter with a line feed character. There are multiple methods that can do the job, but I will show what I think is the easiest to work with.
First define a variable containing a single linefeed
The next trick is to replace spaces in your variable with linefeeds. Normally substituion using a variable for the replacement would look something like
set "var=!var:search=%replaceVar%!". But that won’t work for the LF variable – it is difficult to work with the LF variable using normal expansion. It is much easier to use delayed expansion. We can’t embed delayed expansion within delayed expansion, but we can transfer the value of LF to a simple FOR variable and usefor %%L in ("!LF!") do set "var=!var: =%%~L!"One thing about your code I do not understand – your initial FOR loop is iterating accross all the .KML files. You strip off the extension using a substring operation. There is a much easier way to do that without using an environment variable:
%%~nKwill give the base name of the file without the extension. But why do that at all when you turn around and append the extension again?I used the %%K value directly – I added the USEBACKQ option and added quotes to allow for spaces in the file name.
Here is code that should do what you are expecting.
BUT – I think you have a bigger problem. I am worried that you are setting yourself up for a world of pain by using batch to parse XML. You are assuming the XML will always be layed out the same way. There are countless valid ways of adding or subtracting linefeeds and white space into the XML document that would break your algorithm. Can you be sure all your input files came from the same source and will always be formatted like you expect? I think you really should be using XSLT to parse and transform your XML document into a naked list of coordinates.
Answsers to additional questions
1)
set "var=!var: =%LF%!"will not work – Regular expansion of LF requires escape sequences and multiple expansions. This will work:set "var=!var: =^%LF%LF%!"The escape sequences for %LF% can get very tricky, so I try to avoid them.
2) Regarding
for %%L in ("!LF!") do set "X=!X: =%%~L!", note that it is a simple FOR, not FOR /F. The !LF! must be quoted or else FOR will not read it. But the FOR statement preserves the quotes (unlike FOR /F), so I need %%~L to remove the enclosing quotes.There is a very important distinction between FOR and FOR /F with regard to linefeeds. FOR will preserve quoted linefeeds, whereas FOR /F treats the linefeed as a line delimiter and iterates each line, so the linefeeds are not preserved.