【问题标题】: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

因此,在插入标签之前,我需要检查整行匹配甚至起始部分 -

【问题讨论】:

标签: xml batch-file command-line


【解决方案1】:

尝试仅使用本机 Batch 函数编辑 XML 几乎是不可能完成的任务。像 这样的 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 等工具。

      【讨论】:

        猜你喜欢
        • 2013-01-19
        • 2012-05-28
        • 1970-01-01
        • 1970-01-01
        • 2013-07-18
        • 2020-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多