如何通过批处理文件命令检查 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=".\. &#xA;  (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=".\. &#xA;  (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 元素/属性是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 中使用 SAX Parser 检查 xml 标签是不是具有属性?

如何检查未知的 XML 文件以获取其元素或属性?

检查 XML 节点是不是具有 Linq C# 的属性?

如何检查 XML 中是不是存在特定属性?

如何检查字符串是不是是有效的 XML 元素名称?

检查 XML 是不是存在元素