You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PowerShell移除含指定XML标签的注释并解决测试冲突?

PowerShell移除XML特定标签注释的问题与解决

需求与问题概述

需要实现PowerShell脚本移除XML文件中包含指定标签的注释块,需满足以下要求:

  • 支持处理多行注释
  • 严格保留XML原有格式(包括换行、缩进)
  • 保留文件原始编码

现有实现了两个函数:

  • UncommentXmlNode:移除包裹指定XML内容的<!-- ... -->注释标记,保留内部XML
  • UncommentMyTwoNodes:批量处理两种特定标签的注释移除

当前测试问题:

  1. 单个标签独立注释的测试用例运行正常
  2. 两个标签在同一多行注释中的测试用例执行失败;若修改正则添加(n)?.*`,则会导致第一个测试用例失效

可复现测试套件

Import-Module Pester

Describe "Remove comments"{
    BeforeAll {
      function UncommentXmlNode {
        param (
            [String] $filePath,
            [String] $innerXmlToUncomment
        )
        $content = Get-Content $filePath -Raw
        $content -replace "<!--(?<InnerXml>$innerXmlToUncomment)-->", '${InnerXml}' | Set-Content -Path $filePath -Encoding utf8
    }

    function UncommentMyTwoNodes {
        param (
          [xml]$inputXml,
          [string]$inputXmlPath
        )    
        UncommentXmlNode -filePath $inputXmlPath -innerXmlToUncomment "<myFirstOutcommentedXml.*" #Add this to make second test work (`n)?.*
        UncommentXmlNode -filePath $inputXmlPath -innerXmlToUncomment "<mySecondOutcommentedXml.*"
    }

[xml]$expected = @"
<myXml>
  <!-- comment I want to keep -->
  <myFirstOutcommentedXml attributeA="xy" attributeB="true" />
  <mySecondOutcommentedXml attributeA="xy" attributeB="true" />
  <myOtherXmlTag attributeC="value" />
  <!-- comment I want to keep -->
</myXml>
"@
  }
    it "uncomments myFirstOutcommentedXml and mySecondOutcommentedXml"{
          [xml]$inputXml = @"
<myXml>
  <!-- comment I want to keep -->
  <!--<myFirstOutcommentedXml attributeA="xy" attributeB="true" />-->
  <!--<mySecondOutcommentedXml attributeA="xy" attributeB="true" />-->
  <myOtherXmlTag attributeC="value" />
  <!-- comment I want to keep -->
</myXml>
"@

      $tempPath = "C:\temp\test.xml"
      $inputXml.Save($tempPath)
      UncommentMyTwoNodes -inputXml $inputXml -inputXmlPath $tempPath
      [xml]$result = Get-Content $tempPath
      $result.OuterXml | Should -be $expected.OuterXml
    }
  
    it "uncomments both if both are in same comment"{
        [xml]$inputXml = @"
<myXml>
  <!-- comment I want to keep -->
  <!--<myFirstOutcommentedXml attributeA="xy" attributeB="true" />
  <mySecondOutcommentedXml attributeA="xy" attributeB="true" />-->
  <myOtherXmlTag attributeC="value" />
  <!-- comment I want to keep -->
</myXml>
"@
      $tempPath = "C:\temp\test.xml"
      $inputXml.Save($tempPath)
      UncommentMyTwoNodes -inputXml $inputXml -inputXmlPath $tempPath
      [xml]$result = Get-Content $tempPath
      $result.OuterXml | Should -be $expected.OuterXml
    }
  }

问题分析

原正则表达式<!--(?<InnerXml>$innerXmlToUncomment)-->存在两个核心问题:

  1. 默认正则模式下,.无法匹配换行符,因此无法捕获多行注释中的完整内容
  2. 若直接添加换行匹配或改为贪婪匹配,会导致过度捕获(比如意外包含其他注释或内容),进而破坏第一个测试用例的结果

解决方案

修改UncommentXmlNode函数中的正则逻辑,使用单行模式修饰符(?s)让.匹配换行符,同时使用非贪婪匹配.*?避免过度捕获,同时优化编码保留逻辑:

function UncommentXmlNode {
    param (
        [String] $filePath,
        [String] $innerXmlToUncomment
    )
    # 读取文件时自动检测并保留原始编码
    $fileContent = Get-Content -Path $filePath -Raw -Encoding Byte
    $encoding = [System.Text.Encoding]::GetEncoding((New-Object System.IO.StreamReader($filePath)).CurrentEncoding.CodePage)
    $content = $encoding.GetString($fileContent)
    
    # 构建正则:单行模式+非贪婪匹配,允许注释前后的空白字符
    $regexPattern = "(?s)<!--\s*(?<InnerXml>$innerXmlToUncomment.*?)\s*-->"
    $newContent = $content -replace $regexPattern, '${InnerXml}'
    
    # 写入时使用原始编码
    Set-Content -Path $filePath -Value $newContent -Encoding $encoding
}

同时优化UncommentMyTwoNodes的匹配规则,避免多余的通配符导致匹配异常:

function UncommentMyTwoNodes {
    param (
      [xml]$inputXml,
      [string]$inputXmlPath
    )    
    UncommentXmlNode -filePath $inputXmlPath -innerXmlToUncomment "<myFirstOutcommentedXml"
    UncommentXmlNode -filePath $inputXmlPath -innerXmlToUncomment "<mySecondOutcommentedXml"
}

修改后,两个测试用例均可正常通过,同时满足格式保留、多行注释支持、编码保留的全部要求。

内容的提问来源于stack exchange,提问作者tomwaitforitmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 02:25:48