Reputation: 51
I need to read a path from an attribute in an XML file but spaces are making me problems.
@echo off
:: Write a VBS file for getting modfolder from gameSettings.xml
> "%TEMP%\moddir.vbs" (
echo.Dim oXml: Set oXml = CreateObject^("Microsoft.XMLDOM"^)
echo.oXml.Load WScript.Arguments.Item^(0^)
echo.Dim oDoc: Set oDoc = oXml.documentElement
echo.
echo.For Each node In oDoc.childNodes
echo. If ^(node.nodeName = "modsDirectoryOverride"^) And ^(node.getAttribute^("active"^) = "true"^) Then
echo. WScript.Echo node.getAttribute^("directory"^)
echo. End If
echo.Next
echo.Set oXml = Nothing
)
:: Setting Mod directory
SETLOCAL
for /f %%i in ('cscript %TEMP%\moddir.vbs "%UserDocs%\My Games\FarmingSimulator2017\gameSettings.xml" //Nologo') do set "moddir=%%i"
echo moddir = %moddir%
The line in the XML file is:
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<gameSettings revision="11">
<modsDirectoryOverride active="true" directory="D:\games\Farming Simulator\Farming simulator 17\Mods"/>
</gameSettings>
The variable moddir
is set to D:\games\Farming
although it should be D:\games\Farming Simulator\Farming simulator 17\Mods
.
Upvotes: 0
Views: 320
Reputation: 67216
I offer you a pure Batch file alernative solution that is simpler, but have the disadvantage that it only works with the xml file format you shown.
The findstr
command can extract lines from a file that have a given string. For example, findstr "modsDirectoryOverride" "gameSettings.xml"
command show this line:
<modsDirectoryOverride active="true" directory="D:\games\Farming Simulator\Farming simulator 17\Mods"/>
If we separate this line based on for /F
command, that use the space as default separator, and include these options: for /F "tokens=1,2*" %%a in ('previous line') do ...
, you'll realize that the for
parameters have these values:
%%a have <modsDirectoryOverride
%%b have active="true"
%%c have directory="D:\games\Farming Simulator\Farming simulator 17\Mods"/>
Then, we can execute set %%b
and set %%c
commands, that would be equivalent to these commands:
set active="true"
set directory="D:\games\Farming Simulator\Farming simulator 17\Mods"/>
After that, you just need to test if %active%
is "true"
to show the directory, and that is it! ;)
The only detail is that the value of %directory%
start with quote and ends with "/>
, so these characters must be stripped from the output:
@echo off
setlocal
for /F "tokens=1,2*" %%a in ('findstr "modsDirectoryOverride" "gameSettings.xml"') do (
set %%b
set %%c
)
if %active% equ "true" echo %directory:~1,-3%
Upvotes: 1
Reputation: 80023
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q41196420.txt"
FOR /f "usebackqtokens=1,3delims=<=>/" %%a IN ("%filename1%") DO (
IF "%%~a"=="modsDirectoryOverride active" ECHO dir=%%~b
)
GOTO :EOF
You would need to change the setting of sourcedir
to suit your circumstances.
I used a file named q41196420.txt
containing your data for my testing.
Here's an easy way - simply select suitable tokens and delimiters and filter with an if
Best to provide the problem to be solved, not a solution-to-fix alone.
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q41196420.txt"
FOR /f "usebackqtokens=1-7delims=<=>/" %%a IN ("%filename1%") DO (
ECHO + %%a + %%b + %%c + %%d + %%e + %%f + %%g +
REM note content of "%%x" - %%~x = %%x minus quotes at either end
REM we may need to tokenise "%%a" using spaces as delimiters
FOR /f "tokens=1*delims= " %%m IN ("%%a") DO (
REM %%a..%%g, %%m and %%n are in-context
ECHO + %%m + %%n
REM same formula for "%%b"
FOR /f "tokens=1*delims= " %%p IN ("%%b") DO (
REM %%a..%%g, %%m and %%n are in-context
ECHO + %%p + %%q
ECHO + %%a + %%b + %%c + %%d + %%e + %%f + %%g + %%m + %%n + %%p + %%q +
REM So, select your parts. if /i=case-insensitive since I abhor CaMeLcAsE
IF /i "%%~m"=="modsdirectoryoverride" IF /i "%%n"=="active" IF /i "%%~p"=="true" ECHO.&ECHO ***Directory=%%~c*** or ***Directory=%%c*** as you wish
)
)
REM %%a..%%g are in-context, %%m and %%n are not
ECHO.
)
GOTO :EOF
If you read the documentation (for /? |more
from the prompt) then you'll likely be befuddled.
The code above displays how the line can be disassembled in batch, the important point being the conditional selection of the directoryname.
Take any line of text. This could be one of a series of lines in a file, a series of lines output from a command or even a variable.
First, you use delims
to specify what delimiters to use. The line is seen as a series of tokens separated by a [sequence of] delimiter[s]
so abc/123:ghij/:/hello
is seen as tokens abc
, 123
, ghij
and hello
if delims
is set to /:
. By default, it is set to comma and space.
The tokens
keyword assigns the selected strings to metavariables
(the loop-control variables+). If the metavariable is %%a
then the lowest selected token is assigned to %%a
, the next lowest to %%b
and so on. *
is a special which means "everything after the highest token selected, including delimiters". tokens
defaults to 1
.
So, applying tokens=1,3
to the above tokenised abc/123:ghij/:/hello
with metavariable %%a
will set %%a=abc
(1st) and %%b=ghij
(3rd).
Beyond that, you may need usebackq
to allow a filename in quotes (required if the full name includes spaces) to be read; if usebackq
is omitted, a quoted string will be used literally.
Upvotes: 1