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
set LF=^
::The two blank lines above are critical for the definition of the line feed
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 use for %%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: %%~nK
will 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.
@echo off
setlocal EnableDelayedExpansion
::define a variable containing a linefeed character
set LF=^
::Above 2 blank lines are part of the LF definition, do not remove
for %%K in (*.kml) do (
set "prep=0"
for /f "usebackq tokens=*" %%X in ("%%K") do (
if !prep! == 1 (
echo %%X
pause
set "ln=%%X"
for %%L in ("!LF!") do set "ln=!ln: =%%~L!"
for /f %%L in ("!ln!") do (
set L=%%L
if not "!L:~0,1!" == "<" (
echo %%L
)
)
set "prep=0"
)
if "%%X" == "<coordinates>" ( set "prep=1" )
)
)
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.