windowsbatch-filexml-parsingdynamic-variables

How to assign values to environment variables with dynamic name while parsing similar named XML elements?


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.


Solution

  • 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.

    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.