仅当两个值匹配时才从XML文件中提取数据。 (使用.bat)

时间:2017-04-10 04:27:11

标签: xml batch-file

我正在寻找一个.bat脚本,该脚本运行我的XML文件并仅提取指定XML文件的某些数据。如果名称“Ian”和位置“executive”匹配,则只应提取这些XML文件的数据。如果.bat找到匹配的XML文件,它应该只提取3个指定的值。

例如:

仅提取if:

  1. 价值将是“Name = Ian”
  2. 价值将是“Postition = Executive”
  3. 如果这些值匹配,则应提取数据:

    1.currentWork

    2.shortID

    3.holidaycounter

    我希望这不会太多工作。 XML数据都很相似。

    <Name="Ian" workstampIN="2017-04-06" worknumber="XXXX" editor="XXXX" Position="Executive" currentWork="engineer" shortID="543532" holidaycounter="50" >
    

    抱歉,我对.bat真的很新。感谢您的帮助!

4 个答案:

答案 0 :(得分:0)

考虑一下:batch是解析XML文件的不错选择。也就是说:使用适当的令牌和分隔符,使用for循环提取数据:

@echo off
setlocal
for %%z in (*.xml) do call :extract %%z
goto :eof

:extract
for /f "tokens=1-8 delims=<> " %%a in (%*) do (
  set _%%a
  set _%%e
  set _%%f
  set _%%g
  set _%%h
)
REM set _
if %_Position%=="Executive" if %_Name%=="Ian" (
  echo 1. %_currentWork%
  echo 2. %_shortID%
  echo 3. %_holidaycounter%
) >> outputfile.txt
goto :eof

答案 1 :(得分:0)

@ECHO OFF
SETLOCAL enabledelayedexpansion
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q43314990.txt"
SET /a filtercount=0
SET /a fieldcount=0
CALL :filterset %*
IF %filtercount%==0 GOTO syntax
IF %fieldcount%==0 GOTO syntax
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
 SET "line=%%a"
 SET "line=!line:<=!"
 SET "line=!line:>=!"
 SET "line=!line::==!"
 CALL :filter !line!
)

GOTO :EOF

:syntax
ECHO syntax is [requiredname requiredvalue]* :: reportfieldname*
GOTO :EOF


:: set and count filters and fields

:filterset
IF "%~1"=="::" GOTO fieldset
IF "%~1"=="" GOTO :EOF 
SET /a filtercount +=1
SET "$%filtercount%=%~1"
shift
SET "#%filtercount%=%~1"
shift
GOTO filterset

:fieldset
shift
IF "%~1"=="" GOTO :EOF 
SET /a fieldcount +=1
SET "_%fieldcount%=%~1"
GOTO fieldset

:filter
FOR /L %%z IN (1,1,%fieldcount%) DO SET "@%%z="
SET /a matchesfound=0
:filterloop
IF "%~1"=="" GOTO report
FOR /L %%z IN (1,1,%filtercount%) DO IF /i "%~1>%~2"=="!$%%z!>!#%%z!" SET /a matchesfound+=1
FOR /L %%z IN (1,1,%fieldcount%) DO IF /i "%~1"=="!_%%z!" SET "@%%z=%~2"
SHIFT
shift
GOTO filterloop

:report
IF %matchesfound% neq %filtercount% GOTO :EOF 
SET "reportline="
FOR /L %%z IN (1,1,%fieldcount%) DO SET "reportline=!reportline! !@%%z!
ECHO(%reportline:~1%
GOTO :eof

您需要更改sourcedir的设置以适合您的具体情况。

我使用了一个名为q43314990.txt的文件,其中包含您的数据和一些虚拟数据供我测试。

此程序可以解决您的问题。

我假设调用它的批处理命令是

  

thisbatch cls&amp; q43314990 name ian position executive :: currentWork shortid holidaycounter

那是(fieldname requiredvalue)根据需要重复多次&#39; ::`(reportfiledname)重复多次

和那个案子无关。

第一个操作是按call :filterset分析命令行。如果未同时指定过滤器和报告字段,则显示所需的语法。

否则,请将每个文件行读取到%%a,然后读取到line。处理line以移除><并将:转换为=(如果:应为=,则不需要您的示例),然后调用:filter以提取所需数据并进行报告。

:filterset例程会查看第一个标记,并将其记录为$1,并将相应的值记录为#1,并继续使用$2,#2等,直到{{找到1}}(每个名称/值对被::命令移出(一个左边),分隔名称/值的shift Space 有助于替换byy =机制)

找到call后,其余参数将记录为::_1等 - 这些是要报告的字段名称。

_2例程首先清除所有要报告的字段数的:filter值。

然后,@?提供的第一个和第二个参数与call(之前删除的字符)连接,因此不存在,因此可用于分隔字段)并与从$ 1&gt;#1 .. $?&gt;#?构成的相同字符串进行比较在比赛中,计算比赛次数。

然后查看>中的字段名是否与%1中的每个必需输出字段名匹配,如果是,则将该参数的值从_?记录到%2

然后@?两次删除名称/值对并执行到下一个。

如果没有剩下参数,只有在找到的匹配的nuber与过滤器的数量相同时才会报告。在这种情况下,只需通过连接空格后每个选定字段的值来构建报表行。最终报告是shift跳过第一个字符(这将是一个空格)

答案 2 :(得分:0)

给定的XML节点无效,因为它不能仅包含attributes。这是我用于测试的xml:

<root>
    <N Name="Ian" workstampIN="2017-04-06" worknumber="XXXX" editor="XXXX" Position="Executive" currentWork="engineer" shortID="543532" holidaycounter="50"/>
</root>

使用xpath.bat,您可以使用以下表达式:

call xpath.bat name.xml "//N[@Name='Ian'][@Position='Executive']/@shortID"

答案 3 :(得分:0)

当我审查这种类型的“问题”(没有OP写的代码)时,我认为他们是写作我想要的任何内容的许可;例如:

@echo off
setlocal EnableDelayedExpansion

(for /F "tokens=1,2 delims=:<>" %%a in ('findstr "Name=\"Ian\" Position=\"Executive\"" *.xml') do (
   set "list=%%b"
   for /F "delims=" %%c in (^"!list: ^=^
% Do NOT remove this line %
!^") do set %%c
   if "!Name!+!Position!" equ ""Ian"+"Executive"" (
      echo File: "%%a", currentWork=!currentWork!, shortID=!shortID!, holidaycounter=!holidaycounter!
   )
)) > Outputfile.txt