1

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.

5
  • It would help us if you were to show us the set command you say is not working for you. Are you using Call Set "pool%%x%%=%%a"? or something different? Also the whitespece at the beginning of those lines are assigned to the first token and the string pool to the second token, so I doubt very much that your call ECHO pool%%x%%=%%a line is providing the output you suggest it is. You will want the third token, tokens=3. Commented Feb 15, 2021 at 17:42
  • BTW, as you've already enabled delayed expansion, there's no need, (and it's slower), to use call with %%x%%. You can just delete call and use Set "pool!x!=%%a" instead. Commented Feb 15, 2021 at 17:49
  • @Compo: Thank you for your response. But I am expecting the output in the same way as Mofi has said in his response. Commented Feb 15, 2021 at 19:05
  • @Pankaj, unless I'm going demented, or senile, (no comments please), @Mofi, has used exactly the same techniques as in my comments, both with Call, and without when using delayed expansion. The only difference is they included the whitespace, (which is already the default option), with their delimiters, and could therefore continue using the second token, if you remove those and stick only with <>, the third token will serve you just as well! Commented Feb 15, 2021 at 20:53
  • @Compo: Thank you for your response. I am new to this and I am learning. I will make note of your point too. Commented Feb 16, 2021 at 11:38

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0
...
set /a "x+=1" 
call SET pool%%x%%=%%a
)
SET pool

The first set assigns the value in %%a to the variable pool?

The second set displays all of the currently-set environment variables whose name starts pool.

setx is a command designed to record a variable assignment for future instances of cmd. It's an entirely different matter and should be raised as a separate question, but there's plenty of SO items about setx so raising it (again) as a separate issue will likely be closed as a duplicate. Best use the search facility for setx.

1 Comment

Thank you for your response and the explanation @Magoo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.