I have an XML file in the following manner:
<pools>
<pool>aaa</pool>
<pool>bbb</pool>
<pool>ccc</pool>
<pool>ddd</pool>
<pool>eee</pool>
</pools>
I want to parse these tags in such a way that they will be assigned to variables as
Pool1 = aaa
Pool2 = bbb
and so on
I have tried the below code:
echo off
set /a x=0
SETLOCAL enableextensions enabledelayedexpansion
for /f "tokens=2 delims=<>" %%a in ('find /i "<pool>" ^< "pool_info.xml"') do (
set /a "x+=1"
call ECHO pool%%x%%=%%a
)
And it just prints them properly. I tried the set
command for assigning them, but it does not work.
I went through many Stack Overflow problems, but was not able to find any solution that would match my requirement. If anyone could please help me out.
PS: The <pool>
tags count here is 5, however, the count can change, so I want it to be flexible.
The task can be done with:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Delete all environment variables of which name starts with Pool.
for /F "delims==" %%I in ('set Pool 2^>nul') do set "%%I="
set "PoolCount=0"
for /F "tokens=2 delims=<> " %%I in ('%SystemRoot%\System32\findstr.exe /I /L /C:"<pool>" "pool_info.xml"') do (
set /A PoolCount+=1
call set "Pool%%PoolCount%%=%%I"
)
rem Output all environment variables of which name starts with Pool.
set Pool
endlocal
ATTENTION: The delimiters are the two angle brackets, a horizontal tab character and a normal space character. Please make sure that the batch file contains exactly those four characters after delims=
in that order.
The horizontal tab and the normal space are needed as delimiters to have a working solution independent on leading spaces/tabs on the lines with the pool
elements.
The wrong token respectively the missing delimiters tab/space resulted with posted code in question in getting element name pool
output instead of the values of the XML element pool
.
There is no need to use delayed environment variable expansion in this case.
However, the usage of call
to force a second parsing of the command line
call set "Pool%%PoolCount%%=%%I"
modified already during parsing of the entire command block to
call set "Pool%PoolCount%=%I"
before execution of set
is slower in comparison to using delayed expansion as used in the code below.
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Delete all environment variables of which name starts with Pool.
for /F "delims==" %%I in ('set Pool 2^>nul') do set "%%I="
set "PoolCount=0"
for /F "tokens=2 delims=<> " %%I in ('%SystemRoot%\System32\findstr.exe /I /L /C:"<pool>" "pool_info.xml"') do (
set /A PoolCount+=1
set "Pool!PoolCount!=%%I"
)
rem Output all environment variables of which name starts with Pool.
set Pool
endlocal
The reason is explained by jeb in the DosTips forum post CALL me, or better avoid call. The Windows command processor searches with using call set "Pool%%PoolCount%%=%%I"
in the batch file in current directory and next in all directories of environment variable PATH
for a file matching the wildcard pattern set.*
. If there is indeed a file found like set.txt
in one of the directories, it searches next in that directory for set.COM
, set.EXE
, set.BAT
, set.CMD
, ... according to list of file extensions of environment variable PATHEXT
. If there is really an executable or script found by cmd.exe
with file name set
in current directory or another other directory of PATH
with a file extension of PATHEXT
, it executes the executable/script instead of running internal command SET.
For that reason it is definitely better to use delayed expansion solution as it is faster and more safe.
The disadvantage is that a pool
value with one or more !
is not correct processed with enabled delayed expansion. So once again cmd.exe
proves itself that the Windows command processor is designed for executing commands and executables, but not for processing data in text files.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
call /?
... used for double parsing the command line before execution of set
.echo /?
endlocal /?
findstr /?
for /?
rem /?
set /?
setlocal /?
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul
. The redirection operator >
must be escaped with caret character ^
on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded set
command line with using a separate command process started in background with %ComSpec% /c
and the command line within '
appended as additional arguments.