如何使用纯批处理从单行XML文件中获取多个属性值?
我需要从一行格式化的XML文件的多个属性中获取值 我已经检查了许多示例,但是由于单行文件的缘故,没有一个真正适合我 首先,我尝试使用findstr命令,但这并没有真正的帮助,因为它总是返回整行(在我的例子中是所有内容),而且显然不可能使用REGEX获取值,而只能找到正确的行。 e、 g.喜欢如何使用纯批处理从单行XML文件中获取多个属性值?,xml,batch-file,Xml,Batch File,我需要从一行格式化的XML文件的多个属性中获取值 我已经检查了许多示例,但是由于单行文件的缘故,没有一个真正适合我 首先,我尝试使用findstr命令,但这并没有真正的帮助,因为它总是返回整行(在我的例子中是所有内容),而且显然不可能使用REGEX获取值,而只能找到正确的行。 e、 g.喜欢 findstr /c:"testCase=" test_case_run_log_report.xml 然后我尝试在FOR命令中使用delims和token。如果它确实是根据输入文件指定的,那么这种方法
findstr /c:"testCase=" test_case_run_log_report.xml
然后我尝试在FOR命令中使用delims和token。如果它确实是根据输入文件指定的,那么这种方法可能有效,但我需要一种通用方法,因为xml文件每次启动时可能包含更多的“testCaseRunLogTestStep”步骤。这实际上是一个有效的解决方案,至少在XML不会只存储在一行的情况下是这样。
e、 g.(此处的令牌编号不准确,但如前所述,也不能使用此解决方案)
因此,我的想法是将文件内容拆分为“/>”,然后可能运行FOR命令并进行一些处理。但这对我来说太过分了
这就是XML文件的外观
<?xml version="1.0" encoding="UTF-8"?>
<con:testCases testCase="testCase1" timeTaken="201" status="FINISHED" timeStamp="2019-07-25 09:00:47" xmlns:con="http://xx/config"><con:testCaseRunLogTestStep name="testStep1" timeTaken="222" status="OK" timestamp="2019-07-25 09:00:45" httpStatus="200" contentLength="9" readTime="6" totalTime="216" dnsTime="0" connectTime="117" timeToFirstByte="93" httpMethod="GET" /> <con:testCaseRunLogTestStep name="testStep2" timeTaken="528" status="OK" timestamp="2019-07-25 09:00:46" httpStatus="200" contentLength="0" readTime="0" totalTime="529" dnsTime="0" connectTime="1" timeToFirstByte="528" httpMethod="GET"/></con:testCases>
例如:
testStep1=OK
testStep2=OK
我曾经使用过PowerShell,但后来在不同服务器上安装了不同版本的PowerShell时遇到了问题。
所以出于兼容性的原因,我切换到了纯批处理,它在不同的任务中一直工作得很好,直到现在
我自己也是开发人员,但这项任务让我感觉像爱丽丝梦游仙境。这里有一个批处理文件,只使用Windows命令处理器的内部命令
cmd.exe
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "XmlFile=test_case_run_log_report.xml"
if not exist "%XmlFile%" (
echo ERROR: File "%XmlFile%" not found.
goto :EOF
)
rem Assign last non-empty line of specified XML file not starting
rem with a semicolon to environment variable XmlLine if not longer
rem than 8181 characters. Maximum length of "XmlLine=..." is 8191
rem characters and so maximum value length is 8181 characters.
set "XmlLine="
for /F "usebackq delims=" %%I in ("%XmlFile%") do (
set "XmlLine=%%I"
set "NewLine=!XmlLine:"=!"
if /I "!NewLine!" == "<?xml version=1.0 encoding=UTF-8?>" set "XmlLine="
)
if not defined XmlLine (
echo ERROR: File "%XmlFile%" is empty or contains too much data.
goto :EOF
)
for %%I in ("%XmlFile%") do set "ResultFile=%%~dpnI.txt"
del "%ResultFile%" 2>nul
rem Remove everything from beginning of line to end of the string between *
rem and = and assign this remaining part of the line to variable NewLine.
rem If nothing was removed, there is no more tag con:testCaseRunLogTestStep
rem with a space and attribute name in remaining line. Otherwise get values
rem of attribute name and status and output both into result file.
:GetNameStatus
set "NewLine=!XmlLine:*<con:testCaseRunLogTestStep name=!"
if not "!NewLine!" == "!XmlLine!" (
set "XmlLine=!NewLine!"
for /F "tokens=1,5 delims== " %%I in ("!XmlLine!") do echo %%~I=%%~J>>"%ResultFile%"
goto GetNameStatus
)
rem Delete result file if existing but file size is less or equal 2 bytes.
if exist "%ResultFile%" for %%I in ("%ResultFile%") do if %%~zI LEQ 2 del "%ResultFile%"
if not exist "%ResultFile%" (
echo ERROR: No element con:testCaseRunLogTestStep with attributes name and status
echo found in file "%XmlFile%".
)
endlocal
此解决方案适用于单行和多行XML文件,无行长度限制(可用的空闲RAM除外)。在元素con:testCaseRunLogTestStep
中,属性name
和status
的位置也更灵活,只要该元素包含第一个name
和下一个status
cscript.exe
执行的区分大小写的JScript搜索正则表达式表示:
。。。任何空格或任何非空格字符0次或以上非贪婪。所以这个表达式将从文件开头或上一个匹配的结尾到[\s\s]*?
的所有内容匹配一次或多次。因此,这个表达式将start标记之后的所有内容匹配到标记中的属性name
。。。必须在下一个字符串name=\x22
中找到正匹配。双引号字符是使用其十六进制表示形式指定的,作为参数字符串,在Windows命令行上通常不能包含name=“
”
…(
。。。第一标记组。此第一个标记组中的表达式找到的字符串在替换字符串中被)
反向引用$1
。。。除[^\x22]+
以外的任何字符都可以使用一次或多次。此表达式与属性名称的值匹配“
…就像前面的任何字符不是[^>]+?
一次或多次非贪婪。因此,此表达式匹配标记中从属性名称
的值之后的
到属性“
状态的所有内容
。。。接下来必须找到字符串状态=\x22
”以进行正匹配status=“
…(
…第二个标记组。此第二个标记组中的表达式找到的字符串在替换字符串中被)
反向引用$2
…与任何字符之前的相同,除了[^\x22]+
一次或多次。此表达式与属性“
的值匹配状态
。。。任何字符不是[^>]+>
一次或多次出现
,然后出现
。此表达式匹配从属性值状态
之后的
到内联元素末尾的所有内容“
con:testCaseRunLogTestStep
…(?:
…非标记组匹配(可选))?
…任何空格字符0次或更多次,字符串\s*\s*
再次任何空格字符0次或更多次。此可选应用表达式将
的最后一个标记后的所有内容匹配到文件结尾,只要文件以结束标记con:testcase runlogteststep
结尾
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读为每个命令显示的所有帮助页面
呼叫/?
del/?
echo/?
endlocal/?
获取/?
goto/?
如果/?
rem/?
设置/?
setlocal/?
jrepl.bat/?
testStep1=OK
testStep2=OK
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "XmlFile=test_case_run_log_report.xml"
if not exist "%XmlFile%" (
echo ERROR: File "%XmlFile%" not found.
goto :EOF
)
rem Assign last non-empty line of specified XML file not starting
rem with a semicolon to environment variable XmlLine if not longer
rem than 8181 characters. Maximum length of "XmlLine=..." is 8191
rem characters and so maximum value length is 8181 characters.
set "XmlLine="
for /F "usebackq delims=" %%I in ("%XmlFile%") do (
set "XmlLine=%%I"
set "NewLine=!XmlLine:"=!"
if /I "!NewLine!" == "<?xml version=1.0 encoding=UTF-8?>" set "XmlLine="
)
if not defined XmlLine (
echo ERROR: File "%XmlFile%" is empty or contains too much data.
goto :EOF
)
for %%I in ("%XmlFile%") do set "ResultFile=%%~dpnI.txt"
del "%ResultFile%" 2>nul
rem Remove everything from beginning of line to end of the string between *
rem and = and assign this remaining part of the line to variable NewLine.
rem If nothing was removed, there is no more tag con:testCaseRunLogTestStep
rem with a space and attribute name in remaining line. Otherwise get values
rem of attribute name and status and output both into result file.
:GetNameStatus
set "NewLine=!XmlLine:*<con:testCaseRunLogTestStep name=!"
if not "!NewLine!" == "!XmlLine!" (
set "XmlLine=!NewLine!"
for /F "tokens=1,5 delims== " %%I in ("!XmlLine!") do echo %%~I=%%~J>>"%ResultFile%"
goto GetNameStatus
)
rem Delete result file if existing but file size is less or equal 2 bytes.
if exist "%ResultFile%" for %%I in ("%ResultFile%") do if %%~zI LEQ 2 del "%ResultFile%"
if not exist "%ResultFile%" (
echo ERROR: No element con:testCaseRunLogTestStep with attributes name and status
echo found in file "%XmlFile%".
)
endlocal
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "XmlFile=test_case_run_log_report.xml"
if not exist "%XmlFile%" (
echo ERROR: File "%XmlFile%" not found.
goto :EOF
)
if not exist "%~dp0jrepl.bat" (
echo ERROR: Batch file "%~dp0jrepl.bat" not found.
goto :EOF
)
for %%I in ("%XmlFile%") do (
set "ResultFile=%%~dpnI.txt"
set "XmlFileSize=%%~zI"
)
del "%ResultFile%" 2>nul
call "%~dp0jrepl.bat" "[\s\S]*?<con:testCaseRunLogTestStep[\s\S]+?name=\x22([^\x22]+)[^>]+?status=\x22([^\x22]+)[^>]+>(?:\s*</con:testCases>\s*)?" "$1=$2\r\n" /M /XSEQ /F "%XmlFile%" /O "%ResultFile%"
if exist "%ResultFile%" for %%I in ("%ResultFile%") do if %%~zI == %XmlFileSize% del "%ResultFile%"
if not exist "%ResultFile%" (
echo ERROR: No element con:testCaseRunLogTestStep with attributes name and status
echo found in file "%XmlFile%".
)
endlocal