如何通过批处理文件命令检查 xml 元素/属性是不是存在
Posted
技术标签:
【中文标题】如何通过批处理文件命令检查 xml 元素/属性是不是存在【英文标题】:How to check for the existence of an xml element/attribute through batch file commands如何通过批处理文件命令检查 xml 元素/属性是否存在 【发布时间】:2021-10-03 07:42:33 【问题描述】:我必须通过批处理文件将 xml 元素插入到 xml 文件中。经过大量研究,我能够使用以下代码实现。但是如果元素/行已经存在,我不应该添加它。
我的 xml 文件如下所示:
<?xml version="1.0"?>
<PastFiles Iterations="1" MaxTimeFrame="20min">
<FileDefinition OrderNum="1" Directory="LOG" PurgeInSubdirectories="No" FilePattern=".\.
(txt|log|html|xml|csv)" MaxSize="10MB" PastFilesOlderThan="10day"/>
</PastFiles>
我能够插入 xml 元素 - " 因此,在插入标签之前,我需要检查整行匹配甚至起始部分 - @echo off
setlocal
>"newfile1.xml" (
for /f "usebackq delims=" %%I in ("LogConfig_BP.xml") do (
set "line=%%I"
setlocal enabledelayedexpansion
if not "!line!"=="!line:/PastFiles=!" (
echo ^<FileDefinition OrderNum="14" Directory="TRACE" PurgeInSubdirectories="Yes" DeleteEmptySubDirs="Yes" FilePattern="*" PastFilesOlderThan="28day"/^>
)
endlocal
echo %%I
)
)
type "newfile1.xml"
pause
【问题讨论】:
ruby、perl、python 都有 xml 解析器。或者使用 xmlstarlet。 请阅读“What should I do when someone answers my question?”。 【参考方案1】:尝试仅使用本机 Batch 函数编辑 XML 几乎是不可能完成的任务。像 xidel 这样的 XML 解析器会为您省去很多麻烦!
xidel -s LogConfig_BP.xml -e "serialize(x:replace-nodes(//FileDefinition[last()],function($x)$x,if ($x[@OrderNum='14']) then () else <FileDefinition OrderNum='14' Directory='TRACE' PurgeInSubdirectories='Yes' DeleteEmptySubDirs='Yes' FilePattern='*' PastFilesOlderThan='28day'/>),'indent':true())" --output-declaration="<?xml version='1.0'?>"
<?xml version='1.0'?>
<PastFiles Iterations="1" MaxTimeFrame="20min">
<FileDefinition OrderNum="1" Directory="LOG" PurgeInSubdirectories="No" FilePattern=".\. 
 (txt|log|html|xml|csv)" MaxSize="10MB" PastFilesOlderThan="10day"/>
<FileDefinition OrderNum="14" Directory="TRACE" PurgeInSubdirectories="Yes" DeleteEmptySubDirs="Yes" FilePattern="*" PastFilesOlderThan="28day"/>
</PastFiles>
美化查询以获得更好的可读性(以及必要的转义字符):
xidel -s LogConfig_BP.xml -e ^"^
serialize(^
x:replace-nodes(^
//FileDefinition[last()],^
function($x)^
$x,^
if ($x[@OrderNum='14']) then ()^
else ^<FileDefinition OrderNum='14' Directory='TRACE' PurgeInSubdirectories='Yes' DeleteEmptySubDirs='Yes' FilePattern='*' PastFilesOlderThan='28day'/^>^
^
),^
'indent':true()^
)^
" --output-declaration="<?xml version='1.0'?>"
您也可以使用computed constructors 并让serialize()
处理输出声明:
xidel -s LogConfig_BP.xml -e "serialize(x:replace-nodes(//FileDefinition[last()],function($x)$x,if ($x[@OrderNum='14']) then () else element FileDefinition attribute OrderNum '14', attribute Directory 'TRACE', attribute PurgeInSubdirectories 'Yes', attribute DeleteEmptySubDirs 'Yes', attribute FilePattern '*', attribute PastFilesOlderThan '28day'),'indent':true(),'omit-xml-declaration':false())"
<?xml version="1.0" encoding="UTF-8"?>
<PastFiles Iterations="1" MaxTimeFrame="20min">
<FileDefinition OrderNum="1" Directory="LOG" PurgeInSubdirectories="No" FilePattern=".\. 
 (txt|log|html|xml|csv)" MaxSize="10MB" PastFilesOlderThan="10day"/>
<FileDefinition OrderNum="14" Directory="TRACE" PurgeInSubdirectories="Yes" DeleteEmptySubDirs="Yes" FilePattern="*" PastFilesOlderThan="28day"/>
</PastFiles>
xidel -s LogConfig_BP.xml -e ^"^
serialize(^
x:replace-nodes(^
//FileDefinition[last()],^
function($x)^
$x,^
if ($x[@OrderNum='14']) then^
()^
else^
element FileDefinition ^
attribute OrderNum '14',^
attribute Directory 'TRACE',^
attribute PurgeInSubdirectories 'Yes',^
attribute DeleteEmptySubDirs 'Yes',^
attribute FilePattern '*',^
attribute PastFilesOlderThan '28day'^
^
^
),^
'indent':true(),'omit-xml-declaration':false()^
)^
"
还可以查看Xidel online tester。
【讨论】:
【参考方案2】:您可以使用xpath.bat
call xpath.bat xml1.xml "//FileDefinition/@OrderNum1"|findstr "^" >nul 2>&1 || (
echo has NOT file definition
) && (
echo has file definition
)
【讨论】:
【参考方案3】:您的研究不知何故未能提出强有力的建议,这些建议经常在这些专栏中阐明,即您永远不应该尝试在不使用 XML 解析器的情况下直接将 XML 处理为文本。这是使您的代码容易受到 XML 中的琐碎变化(例如更改属性顺序或添加空格)以及生成格式错误的 XML(例如,无法正确转义特殊字符)的秘诀。此站点上报告的与不可读 XML 相关的大部分问题都是其根本原因。
使用 XSLT 进行转换,并从 shell 命令调用 XSLT。理想情况下,使用 ant 或 gradle 来控制处理管道,而不是 bash。
或者,对于简单的操作,可以从命令行调用 xmlstarlet 或 Saxon Gizmo 等工具。
【讨论】:
以上是关于如何通过批处理文件命令检查 xml 元素/属性是不是存在的主要内容,如果未能解决你的问题,请参考以下文章