我编写了下面的代码来读取XML文件(file_1.xml和file_2.xml)并在标记之间提取字符串并将其写入TXT文件。问题是一些字符串包含双引号,然后程序将这些字符作为正确的指令(不是字符串的一部分)......
file_1.xml的内容:
<AAA>C086002-T1111</AAA>
<AAA>C086002-T1222 </AAA>
<AAA>C086002-TR333 "</AAA>
<AAA>C086002-T5444 </AAA>
file_2.xml的内容:
<AAA>C086002-T5555 </AAA>
<AAA>C086002-T1666</AAA>
<AAA>C086002-T1777 "</AAA>
<AAA>C086002-T1888 "</AAA>
我的代码:
@echo off
setlocal enabledelayedexpansion
for /f "delims=;" %%f in ('dir /b D:\depart\*.xml') do (
for /f "usebackq delims=;" %%z in ("D:\depart\%%f") do (
(for /f "delims=<AAA></AAA> tokens=2" %%a in ('echo "%%z" ^| Findstr /r "<AAA>"') do (
set code=%%a
set code=!code:""=!
set code=!code: =!
echo !code!
)) >> result.txt
)
)
我在result.txt中得到了这个:
C086002-T1111
C086002-T1222
C086002-T5444
C086002-T5555
C086002-T1666
事实上,8条线中有3条缺失。这些行包括双引号或包含双引号的后续行...
我如何处理这些字符并将它们视为字符串的一部分?
答案 0 :(得分:2)
请注意 - 使用批处理解析XML是一项有风险的业务,因为XML通常会忽略空格。您编写的任何脚本都可能只需将XML重新格式化为另一个等效的有效表单即可解决。话虽如此......
我没有通过完全解释你观察到的行为来追踪问题,但不平衡的报价引起了这一行的问题:
(for /f "delims=<AAA></AAA> tokens=2" %%a in ('echo "%%z" ^| Findstr /r "<AAA>"') do (
您可以消除这个问题,并通过先前删除任何引号来使您的代码完成工作。
@echo off
setlocal enabledelayedexpansion
del result.txt
for /f "delims=;" %%f in ('dir /b D:\depart\*.xml') do (
for /f "usebackq delims=;" %%z in ("D:\depart\%%f") do (
set code=%%z
set code=!code:"=!
set code=!code: =!
(for /f "delims=<AAA></AAA> tokens=2" %%a in ('echo "!code!" ^| Findstr /r "<AAA>"') do (
echo %%a
)) >> result.txt
)
)
但是你有一个潜在的主要问题。 DELIMS不指定字符串 - 它指定字符列表。因此,DELIMS=<AAA></AAA>
相当于DELIMS=<>/A
。如果你的元素值中有A或/,那么你的代码就会失败。
有一种更好的方法:
首先,您可以使用FINDSTR一次性收集所有文件中的所有<AAA>----</AAA>
行,而不进行任何循环:
findstr /r "<AAA>.*</AAA>" "D:\depart\*.xml"
每个匹配行将作为文件路径输出,后跟冒号,后跟匹配行,如:
D:\depart\file_1.xml:<AAA>C086002-T1111</AAA>
文件路径永远不能包含<
或>
,因此您可以使用以下内容迭代结果,捕获相应的令牌:
for /f "delims=<> tokens=3" %%A in ( ...
最后,您可以在整个循环中放置括号,并重定向一次。我假设您希望每次运行都创建一个新文件,因此我使用>
代替>>
。
@echo off
setlocal enabledelayedexpansion
>result.txt (
for /f "delims=<> tokens=3" %%A in (
'findstr /r "<AAA>.*</AAA>" "D:\depart\*.xml"''
) do (
set code=%%A
set code=!code:"=!
set code=!code: =!
echo(!code!
)
假设您只需要修剪前导或尾随空格/引号,那么解决方案就更简单了。它确实需要奇怪的语法来将引用指定为DELIM字符。请注意,最后一个^
和%%B
之间有两个空格。第一个转义空间被视为DELIM字符。未转义的空格终止FOR / F选项字符串。
@echo off
>result.txt (
for /f "delims=<> tokens=3" %%A in (
'findstr /r "<AAA>.*</AAA>" "D:\depart\*.xml"'
) do for /f delims^=^"^ %%B in ("%%A") do echo(%%B
)
更新以回应评论
我假设您的数据值永远不会包含冒号。
如果要将源文件名附加到每行输出,则只需要更改第一个FOR / F以捕获第一个标记(源文件)以及第三个标记(数据值)。该文件将包含完整路径以及尾随冒号。第二个FOR / F使用~nx
修饰符将文件附加到源数据字符串以仅获取名称和扩展名(无驱动器或路径),并且在DELIMS选项中添加冒号以便修剪尾部冒号关闭。
@echo off
>result.txt (
for /f "delims=<> tokens=1,3" %%A in (
'findstr /r "<AAA>.*</AAA>" "D:\depart\*.xml"'
) do for /f delims^=:^"^ %%C in ("%%B;%%~nxA") do echo %%C
)
答案 1 :(得分:0)
如果我保留@dbenham建议并完成它以回显文件名:
@echo off
>result.txt (
for /f %%f in ("D:\depart\*.xml") do (
for /f "delims=<> tokens=3" %%A in ('findstr /r "<AAA>.*</AAA>" "D:\depart\*.xml"') do (
for /f delims^=^"^ %%B in ("%%A") do (
echo %%B;%%f
)
)
)
)
感谢您对此代码的看法!