0

First post, so sorry if this is a repeat. After looking around a bit I'm not finding any pre-existing answer that suits my needs.

I need to build a batch file that can parse an XML file that looks, in part, something like this:

<parameter>
    <name>description</name>
    <value>something something</value>
</parameter>
<parameter>
    <name>project</name>
    <value>ProjectName</value>
</parameter>
<parameter>
    <name>email group to notify</name>
    <value>EmailGroup</value>
</parameter>

I want to find the value associated with the "Project" parameter. I'm able to get the word "Project" with the below for statement (:job outputs it to a text file without the <name> tags), but I can't figure out how to get it parse the next line where the value is located.

for /f "delims=" %%i in ('findstr /i /c:"<name>project</name>" output.xml') do call :job "%%i"
1
  • XmlStarlet is a command line tool for this kind of thing. Commented Sep 15, 2015 at 19:36

2 Answers 2

1

It's generally more graceful to parse and manipulate XML as XML, rather than as text to scrape and tokenize. That way you aren't so dependent upon anticipating the formatting of the files you're manipulating -- line breaks in the middle of tags, for example. To that end, I suggest that you employ Windows Scripting Host and use the Microsoft.XMLDOM COM object to manipulate the XML DOM.

The following batch + JScript hybrid example should be saved with a .bat extension.

@if (@CodeSection == @Batch) @then

@echo off
setlocal

set "XMLfile=test.xml"
set "XPath=//name[contains(text(),'project')]/../value/text()"

for /f %%I in (
    'cscript /nologo /e:Jscript "%~f0" "%XMLfile%" "/x:%XPath%"'
) do set "projectName=%%I"

echo %projectName%

goto :EOF
@end // end batch / begin JScript hybrid chimera

String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); };
var DOM = WSH.CreateObject('Microsoft.XMLDOM'),
    args = { file: WSH.Arguments(0), XPath: WSH.Arguments.Named('x') };

DOM.load(args.file);
DOM.async = false;
DOM.setProperty('SelectionLanguage', 'XPath');

if (DOM.parseError.errorCode) {
    var e = DOM.parseError;
    WSH.StdErr.WriteLine('Error in ' + args.file + ' line ' + e.line + ' char '
        + e.linepos + ':\n' + e.reason + '\n' + e.srcText);
    WSH.Quit(1);
}

var node = DOM.documentElement.selectSingleNode(args.XPath);
WSH.Echo(node.data.trim());
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks rojo! I ended up going the pure batch way of doing it, but there are some neat ideas here that I'll definitely be learning from.
0
@echo off
setlocal

rem Get the number of the line with the "Project" parameter:
for /F "delims=:" %%i in ('findstr /N /I /C:"<name>project</name>" output.xml') do set "line=%%i"

rem Get the value of 3rd. token in next line:
for /F "skip=%line% tokens=3 delims=<>" %%a in (output.xml) do set "value=%%a" & goto continue
:continue

echo Value of Project: "%value%"
call :job "%value%"

Comments

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.