使用批处理脚本从xml中获取特定单词

时间:2017-06-14 00:23:06

标签: batch-file

我正在尝试使用sfk.exe工具从xml中获取特定单词。它正在做的是获取整个单词/行所在的单词而不仅仅是该单词。我想获取该单词并将其存储在临时文件中,以便稍后存储在变量中。 这些词会改变,基本上是客户端的名称,它会根据客户端的xml而有所不同。

sfk find "C:\Env\Test\test.xml" "Name" > %temp%\Test.tmp

以上代码行提取以下内容: <Org Updated="date" Owner="Test" Version="2/1/3/4"Database="Test" Client="Name">

所以基本上它让我全线,而我只想得到没有引号的“名字”。

3 个答案:

答案 0 :(得分:1)

如果线条布局没有改变,那么你可以试试这个:

Set "Name=Microsoft"

For /F Tokens^=10^ Delims^=^" %%A in (
'Find /I "%Name%"^<"C:\Env\Test\test.xml"') Do Echo "%%A"

作为旁注,您是否要搜索Client=,您可以进一步简化它:

For /F Tokens^=10^ Delims^=^" %%A in (
'sfk find "C:\Env\Test\test.xml" "Client="') Do Echo "%%A"

我已经使用了Findsfk命令,它们可以根据您的需要进行互换。

答案 1 :(得分:1)

虽然批处理文件不是处理XML数据的最佳选择,因为它们本身不支持它们,但我想向您展示一种方法来执行您想要的操作:

@echo off
rem // Capture the output of the `find` command (`sfk` command is not necessary):
for /F "delims=" %%L in ('
    ^< "C:\Env\Test\test.xml" find /I " Client="
') do (
    rem // Store found line in variable:
    set "LINE=%%L"
    setlocal EnableDelayedExpansion
    rem /* Remove everything up to and including the first occurrence of ` Client`
    rem    from the string; then split off the leading `=` and the training `>`;
    rem    finally, remove the surrounding `""` from the remaining string: */
    for /F "delims==>" %%I in ("!LINE:* Client=!") do (
        endlocal
        rem // Return the extracted string:
        echo(%%~I
    )
)

仅当每个适用行中出现 SPACE + Client时,才会生效,后跟= - 符号。此外,此Client=属性必须是包含标记中的最后一个属性,因此整个属性定义Client="Name"必须紧跟>

答案 2 :(得分:1)

虽然Windows批处理可能是一种蹩脚的处理xml,但这个(非常简单)的情况可以使用(非常简单的)脚本解决,该脚本对解析的行的结构提供额外的初步假设。

然而,下面的解决方案强调(尽可能)通用方法,在包含标记内的Client=属性的位置上没有前提,或者在一行内的其单一性(奇点)或前面的数量"双引号等等:

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
for /F "delims=" %%G in ('
      findstr /i /r "\<Client=" "D:\bat\SO\files\q44533501_input.xml"
  ') do (
    rem ECHO=merely debugging output 
        ECHO %%G
    set "_line=%%~G"
    call :lineFound
)
goto :eof

:lineFound
  rem remove cmd-poisonous characters `<` and `>` (replace them with spaces)
  set "_line=%_line:<= %"
  set "_line=%_line:>= %"

  set "_takeNextItem="
  rem parse 
  for %%g in ( %_line% ) do (
    if defined _takeNextItem (
      set "_takeNextItem="
      set "_client=%%~g"
      call :clientSet
    ) else (
      if /I "%%~g" == "Client" set "_takeNextItem=%%~g"
    )
  )
goto :eof

:clientSet
  rem ECHO=merely debugging output;
  rem      handle %_client% variable in desired manner instead 
      ECHO(%_client%
goto :eof

当然,您可以在第4行使用sfk find "C:\Env\Test\test.xml" "Client="命令代替findstr /i /r "\<Client=" "D:\bat\SO\files\q44533501_input.xml"

示例输出(包括调试ECHO %%G以显示输入xml文件的可能变化):

==> D:\bat\SO\q44533501.bat
<Org Updated="date" Owner="Test" Version="2/1/3/4" Database="Test" Client="Name">
Name
<Org Updated="date" Database="Test" Client="Name2" Owner="Test" Version="2/1/3/4">
Name2
<Org Updated="yesterday" Client="Name3"></Org><Org Client="Name4" Updated="today">
Name3
Name4

==>

修改即可。要解释:lineFound部分,让我们看看FOR command(它主要用于处理文件,但您也可以处理文本字符串):

Conditionally perform a command on several files.

Syntax
      FOR %%parameter IN (set) DO command

Key
   set         : A set of one or more files, separated by any standard delimiter.
                 Wildcards can be used.

   command     : The command to carry out, including any command-line parameters.

   %%parameter : A replaceable parameter: e.g. in a batch file use %%G 
                                               (on the command line %G)

并利用我们要解析的xml行只包含set描述中上面提到的标准分隔符的事实,请参阅Delimiters

  

分隔符将一个参数与下一个参数分开 - 它们分开了   命令行为单词。

     

参数通常用空格分隔,但任何一个都是空格   以下也是有效的分隔符:

     
      
  • 逗号(,)
  •   
  • 分号(;)
  •   
  • 等于(=)
  •   
  • Space()
  •   
  • Tab()
  •   

一些示例可能会有所帮助:for %g in ( %_line% ) do …循环过程,逐项_line变量在使用标准分隔符作为项目分隔符将其拆分后。原则上,我们获得一个序列,其中每个属性名称后跟属性值(但标记名称作为第一个项目):

==> for %g in ( %_line% ) do @echo %g
Org
Updated
"date"
Database
"Test"
Client
"Name2"
Owner
"Test"
Version
"2/1/3/4"

==>

请注意,对于此特定示例,_line变量是硬编码的

==> set "_line=<Org Updated="date" Database="Test" Client="Name2" Owner="Test" Version="2/1/3/4">"

==> set "_line=%_line:<= %"

==> set "_line=%_line:>= %"

==> set _line
_line= Org Updated="date" Database="Test" Client="Name2" Owner="Test" Version="2/1/3/4"