使用Windows批处理解析XML文件

13

我该如何从一个XML文件中的标签<LOCATION></LOCATION>之间提取类似于"US_NY"的字符串?我尝试使用FINDSTR,但换行符很棘手。

<?xml version="1.0" encoding="utf-16"?>
<DEVICE>
    <AGENT>
        <VERSION>
            2.0.0.2
        </VERSION>
        <CONNECTION>
            <LOCATION>
                US_NY
            </LOCATION>
            <SERVERIP>
                127.0.0.1
            </SERVERIP>
            <TCPPORT>
                5656
            </TCPPORT>
            <POLLINTERVAL>
                5
            </POLLINTERVAL>
        </CONNECTION>
    </AGENT>
</DEVICE>

确定需要提取什么的逻辑是什么? - MC ND
我想从一些设备中获取位置信息。这些信息存储在不同的XML文件中。因此,我需要提取<location></location>之间的字符串或行。这应该使用Windows批处理脚本完成。 - eichhorn
7个回答

15
你应该使用XML.EXE来读取XML文件。更多详细信息请访问http://xmlstar.sourceforge.net/批处理文件:
@echo off
for /f %%i in ('XML.EXE sel -t -v "//LOCATION" CP.xml') do set var=%%i
echo LOCATION is %var%

输出:

LOCATION is US_NY

9

再来一个

@echo off
    setlocal enableextensions enabledelayedexpansion
    set "xmlFile=%~1"
    for /f "tokens=1,2 delims=:" %%n in ('findstr /n /i /c:"<LOCATION>" "%xmlFile%"') do (
        for /f "tokens=*" %%l in ('type "%xmlFile%" ^| more +%%n') do set "location=%%l" & goto endLoop
    )
:endLoop
    echo %location%

@lucy,看第三行。xmlFile被赋予批处理文件传递的文件名。所以,是的,它就是文件名。 - MC ND
3
使用 findstr 的一个主要问题是它使命令依赖于 XML 文件格式。如果您将多个标签放在同一行上,则无法匹配模式!! - Zahra
@Greenish,我同意,批处理脚本中的XML处理应该使用类似xmlstartlet的工具来完成,但是a)这不是本地解决方案(对于某些环境来说是个问题),b)OP问题中的问题是换行符。 - MC ND

6
这里有一个小脚本xpath.bat,可以通过xpath表达式获取xml节点/属性值,不需要使用外部二进制文件。
对于你的情况,可以按照以下方式使用:
call xpath.bat  "location.xml" "//LOCATION"

或将值分配给变量:
for /f "tokens=* delims=" %%a  in  ('xpath.bat  "location.xml" "//LOCATION"') do (
   set "location=%%a"
)

纯批处理解决方案

 @echo off
        for /f "tokens=1 delims=:" %%L in ('findstr /n "<LOCATION>" some.xml') do ( 
         set begin_line=%%L
        )

        for /f "tokens=1 delims=:" %%L in ('findstr /n "</LOCATION>" some.xml') do ( 
         set /a end_line=%%L+1
        )

        echo showing lines between %end_line% and %begin_line%
        break>"%temp%\empty"
        for /f "delims=" %%l in ('fc "%temp%\empty" "some.xml" /lb  %end_line% /t ^|more +4 ^| findstr /B /E /V "*****" ^| more +%begin_line%') do (
         set "location=%%l"
         goto :break_for
        )
        :break_for
        echo %location%
        del /Q /F "%temp%\empty"

some.xml替换为您的xml名称。

5
如果您想使用助手批处理文件(由aacini提供),那么以下内容可行:

@echo off
for /f "tokens=*" %%a in ('findrepl /i "<location>" /e:"</location>" /o:+1:-1 ^< "file.xml" ') do echo "%%a"

这里使用了一个名为findrepl.bat的辅助批处理文件,可以从https://www.dropbox.com/s/rfdldmcb6vwi9xc/findrepl.bat下载。

请将findrepl.bat放置在与批处理文件相同的文件夹中。


1
聪明的双重用途脚本,可以使用内置的CScript作为CMD和JScript。如果需要,它甚至可以重复使用自身来输入帮助信息。 - Jay
findrepl.bat未来的版本将不再提供。 - lww

3

纯批处理 -

@ECHO OFF
SETLOCAL
SET "location="&SET "grab="
FOR /f "tokens=*" %%a IN (q19722041.xml) DO (
 IF DEFINED grab SET location=%%a&SET "grab="
  IF /i "%%a"=="<LOCATION>" SET grab=Y
)
ECHO found location=%location%
GOTO :EOF

其中q19722041.xml是您的源.xml文件。


1

试试这个:

@echo off
setlocal EnableDelayedExpansion
set lastLine=0
< input.xml (for /F "delims=:" %%a in (
              'findstr /N /C:"<LOCATION>" input.xml') do (
   set /A skip=%%a-lastLine+1, lastLine=%%a+2
   for /L %%i in (1,1,!skip!) do set /P line=
   set /P "line=!line!" & echo:
))

注意:本答案是对这篇论坛帖子的回答(可能由@Aacini提供)的改编:Windows批处理FindStr搜索字符串和匹配行


0

Windows下的sed

sed -n "/<LOCATION>/{n;p}" file.xml

在批处理文件中:
for /f %%a in ('sed -n "/<LOCATION>/{n;p}" file.xml') do set "location=%%a"
echo(%location%

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接