使用批处理解析XML文件以从某些特定节点获取值

时间:2013-03-30 11:59:56

标签: xml batch-file

对于以Lists为父节点的每个节点列表,我想获取/保存前三个节点的变量值,即entryoutput和{{1 }}。 我知道如何用vbscript做到这一点,但是批量生产解决方案对我来说更有意思。 拜托,可以吗?

    

token

任何帮助!!! 谢谢

2 个答案:

答案 0 :(得分:1)

@ECHO OFF
SETLOCAL
CALL :zapvars
FOR /f "tokens=2,3delims=<>" %%i  IN (myxml.xml) DO (
CALL :analyse %%i
IF DEFINED tlist   SET   list=%%i
IF DEFINED tentry  SET  entry=%%j
IF DEFINED ttoken  SET  token=%%j
IF DEFINED toutput SET output=%%j
)

GOTO :eof

:analyse
FOR %%a IN (tlist tentry ttoken toutput) DO (SET %%a=)
ECHO %1|FINDSTR /b "list" >NUL
IF NOT ERRORLEVEL 1 SET tlist=Y&GOTO :EOF 
IF "%1"=="entry" SET tentry=Y&GOTO :EOF 
IF "%1"=="output" SET toutput=Y&GOTO :EOF 
IF "%1"=="token" SET ttoken=Y&GOTO :EOF 
IF NOT "%1"=="/%list%" GOTO :EOF 
:: Found end of list
ECHO list=%list% entry=%entry% output=%output% token=%token%
:zapvars
FOR %%z IN (list entry output token) DO (SET %%z=)
GOTO :eof

真的不那么难。问题是你想在envvars中做的事情。显然,如果你想检查缺失的元素,你只需要使用结果if defined list if defined entry if defined output if defined token

根据输入格式,使用<>对每一行进行标记。第一个选定的标记应用于%%i,第二个标记应用于%%j。该行的第一个标记是前导空格。

因此,

%% i将是节点名称。对于每一行,节点名称将传递给子例程:analyze for er,analysis。

:analyze首先清除每个标记t name,表示token is a名称. First cab off the rank is to see whether the token starts列表, so the token is ECHO ed into FINDSTR which looks for a line beginning ( / b` )“清单”。如果findstring找到它要查找的内容,则ERRORLEVEL设置为0,否则为非零。

如果errorlevel不是1 or greater,那么TLIST设置为Y它可以设置为任何内容 - 只要它设置为SOMETHING即可。然后子程序退出。

如果它不是以list开头的令牌,那么每个目标令牌都会:analyse。如果找到一个,它会设置适当的标志。

最后,如果令牌不是/LISTNAMEBEINGPROCESSED,则例程退出。如果找到/list...,则会显示值标记然后清除。

同时,在FOR循环中,在调用:analyse之后,例程的决定最多包含在tlisttentry,{{ 1}},ttoken)在环境中伪造SET。如果设置了tname,则从相应的元变量 - toutput - 如果设置了%%i的列表名称 - 和tlist - 其他的数据项分配相应的值 - 令牌。对于不感兴趣的节点,%%j不返回任何标志,因此:analyse循环只会进入下一行。

答案 1 :(得分:1)

下面的批处理文件获取/保存所需节点的值并为每个父节点处理它们。此方法允许通过仅更改程序中的一行来修改已处理节点的数量和名称,并且它不使用任何外部命令(* .exe文件)或call命令,因此它很快。

@echo off
setlocal EnableDelayedExpansion
rem Define the names of the desired nodes
set nodes=entry output token
rem Process file lines and get first two tokens separated by <> (ie: %%a=entry, %%b=myEntry)
for /F "tokens=2-3 delims=<>" %%a in (theXMLfile.xml) do (
   set "node=%%a"
   rem If this node is not the end of this record...
   if "!node:~0,5!" neq "/list" (
      rem If this node is one of the desired ones...
      if "!nodes:%%a=!" neq "%nodes%" (
         rem Assign this node into a variable of same name (ie: set entry=myEntry)
         set "%%a=%%b"
      )
   ) else (
      rem ListX node complete: process it, for example:
      ECHO call another.bat !entry! !output! !token!
   )
)

但是,如果输入文件非常大,则使用每个记录执行的call命令可能会使程序花费太长时间。允许程序运行得更快的修改是将所有节点存储在数组中,而不是单个变量,然后将父节点数传递给只调用一次的子例程。

@echo off
setlocal EnableDelayedExpansion
rem Define the names of the desired nodes
set nodes=entry output token
rem Define the index of the next array element
set index=1
rem Process file lines and get first two tokens separated by <> (ie: %%a=entry, %%b=myEntry)
for /F "tokens=2-3 delims=<>" %%a in (theXMLfile.xml) do (
   set "node=%%a"
   rem If this node is not the end of this record...
   if "!node:~0,5!" neq "/list" (
      rem If this node is one of the desired ones...
      if "!nodes:%%a=!" neq "%nodes%" (
         rem Assign this node into THE CURRENT ELEMENT OF AN ARRAY variable of same name (ie: set entry[!index!]=myEntry)
         set "%%a[!index!]=%%b"
      )
   ) else (
      rem ListX node complete: pass to next element of arrays
      set /A index+=1
   )
)
rem Call the subroutine and pass as parameter the number of parent listX nodes
set /A number=index-1
call :anotherSub %number%
goto :EOF

:anotherSub numberOfNodes
rem Process all nodes, for example:
for /L %%i in (1,1,%1) do (
   echo !entry[%%i]! !output[%%i]! !token[%%i]!
)
exit /B

安东尼奥