批处理之家's Archiver

aducyl 发表于 2020-2-18 14:34

【已解决】怎么用bat或vbs替换xml文件中的多部分内容?

[i=s] 本帖最后由 aducyl 于 2020-2-20 00:07 编辑 [/i]

我想替换xml文本中的内容,但是需要满足以下条件:

[color=#ff0000][b]1.[/b][/color]替换多部分内容(即如果被替换的内容在xml中存在,则进行替换)
比如:
将[color=RoyalBlue]Note Bar="9" Pos="12"[/color]替换成[color=RoyalBlue]Note Bar="9" Pos="18"[/color]
将[color=RoyalBlue]Note Bar="9" Pos="40"[/color]替换成[color=RoyalBlue]Note Bar="9" Pos="60"[/color]
将[color=RoyalBlue]EndBar="10" EndPos="16"[/color]替换成[color=RoyalBlue]EndBar="10" EndPos="56"[/color]
将…………(还有很多)

[b][color=#ff0000]2.[/color][/b]不用替换内容(即如果被替换的内容在xml中不存在,则不用进行替换)
比如:如果[color=RoyalBlue]EndBar="16" EndPos="48"[/color]不存在,则不用进行替换
(这个部分我不希望通过列入很多个条件来达到不用替换的效果,只需要简单的语言就可以)

[b][color=#ff0000]3.[/color][/b]被替换和替换的文本内容中必须含有等于号、空格和半角双引号,而且转换前后不能丢失
比如:将[color=RoyalBlue]Note Bar="9" Pos="12"[/color]替换成[color=RoyalBlue]Note Bar="9" Pos="18"[/color],当中的等于号、半角双引号和空格在替换前后不能少。

[b][color=#ff0000]4.[/color][/b]最好是能够另存为一个新的xml文件,且新xml中除了需要被替换的内容变更意外,其余部分的内容不能变(即各种字符串都不能缺少、更改、丢失或删除)
  即使不能另存为新文件,那么执行后覆盖原文件的新文件当中除了需要被替换的内容变更意外,其余部分的内容不能变(即各种字符串都不能缺少、更改、丢失或删除)

[b][color=#ff0000]5.[/color][/b]双击做好的vbs或bat文件后,xml中除了需要被替换的内容变更意外,其余部分的内容不能变(即各种字符串都不能缺少、更改、丢失或删除)

flashercs 发表于 2020-2-18 20:23

[i=s] 本帖最后由 flashercs 于 2020-2-18 20:24 编辑 [/i]

editxml.bat
只要替换内容即可,不需替换的有什么用?[code]<#*,:&cls
@echo off
pushd "%~dp0"
powershell -NoProfile -ExecutionPolicy RemoteSigned -Command ". ([ScriptBlock]::Create((Get-Content -LiteralPath \"%~0\" -ReadCount 0 | Out-String ))) "
popd
pause
exit /b
#>
# modify xml attributes
# 替换内容,格式必须遵守下面样本,不要前加 Note
$hashAttr = @{
  'Bar="9" Pos="12"'        = 'Bar="9" Pos="18"'
  'Bar="9" Pos="40"'        = 'Bar="9" Pos="60"'
  'EndBar="10" EndPos="16"' = 'EndBar="10" EndPos="56"'
}
$xmlfile = "4.xml"
$xmlfilenew = "4_new.xml"

$hashValue = @{ }
$re = [regex]'(\w+)="([^"]*)"'
$xmldoc = New-Object -TypeName System.Xml.XmlDocument
try {
  $xmldoc.Load($xmlfile)
  foreach ($strKey in $hashAttr.Keys) {
    $strXPath = $strKey -replace '\w+=', '@$&' -replace ' @', ' and @'
    $hashValue.Clear()
    foreach ($reMatch in $re.Matches($hashAttr.Item($strKey))) {
      $hashValue.Add($reMatch.Groups[1].Value, $reMatch.Groups[2].Value)
    }
    foreach ($node in $xmldoc.DocumentElement.SelectNodes(".//Note[$strXPath]")) {
      foreach ($dicEntry in $hashValue.GetEnumerator()) {
        $node.SetAttribute($dicEntry.Key, $dicEntry.Value)
      }
    }
  }
  $xmldoc.Save($xmlfilenew)
} catch {
  $_ | Out-String | Write-Host -ForegroundColor Red
}[/code]

aducyl 发表于 2020-2-18 21:37

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=226641&ptid=54875]2#[/url] [i]flashercs[/i] [/b]


怎样才能按照附件BAT文件中的替换顺序对1.xml进行替换,要求:
XML文件中的每一行按照BAT文件中的顺序只进行最初的一次替换就终止(就是不要循环替换,因为有的[b][color=Red]替换内容[/color][/b]可能会变成另一个[b][color=Red]被替换内容[/color][/b],)

有可能进行了多次替换,导致替换结果不对。

更确切地说是按照下面的图片来的
就是 xml文件中的每一行只进行最初的一次就不要再进行替换,保留最初的这一次替换就好

aducyl 发表于 2020-2-18 22:10

[i=s] 本帖最后由 aducyl 于 2020-2-18 22:24 编辑 [/i]

2楼的代码很好,再加上3楼的就更好了~~

flashercs 发表于 2020-2-19 10:24

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=226642&ptid=54875]3#[/url] [i]aducyl[/i] [/b][code]<#*,:&cls
@echo off
pushd "%~dp0"
powershell -NoProfile -ExecutionPolicy RemoteSigned -Command ". ([ScriptBlock]::Create((Get-Content -LiteralPath \"%~0\" -ReadCount 0 | Out-String ))) "
popd
pause
exit /b
#>
# modify xml attributes
# 替换内容,格式必须遵守下面样本,不要前加 Note
$hashAttr = @{
  'Bar="5" Pos="0"'        = 'Bar="5" Pos="0"'
  'Bar="5" Pos="2"'        = 'Bar="5" Pos="2"'
  'Bar="5" Pos="4"'        = 'Bar="5" Pos="6"'
  'Bar="5" Pos="6"'        = 'Bar="5" Pos="8"'
  'Bar="5" Pos="8"'        = 'Bar="5" Pos="12"'
  'Bar="5" Pos="10"'       = 'Bar="5" Pos="14"'
  'Bar="5" Pos="12"'       = 'Bar="5" Pos="18"'
  'Bar="5" Pos="14"'       = 'Bar="5" Pos="20"'
  'Bar="5" Pos="16"'       = 'Bar="5" Pos="24"'
  'Bar="5" Pos="18"'       = 'Bar="5" Pos="26"'
  'Bar="5" Pos="20"'       = 'Bar="5" Pos="30"'
  'Bar="5" Pos="22"'       = 'Bar="5" Pos="32"'
  'Bar="5" Pos="24"'       = 'Bar="5" Pos="36"'
  'Bar="5" Pos="26"'       = 'Bar="5" Pos="38"'
  'Bar="5" Pos="28"'       = 'Bar="5" Pos="42"'
  'Bar="5" Pos="30"'       = 'Bar="5" Pos="44"'
  'Bar="5" Pos="32"'       = 'Bar="5" Pos="48"'
  'Bar="5" Pos="34"'       = 'Bar="5" Pos="50"'
  'Bar="5" Pos="36"'       = 'Bar="5" Pos="54"'
  'Bar="5" Pos="38"'       = 'Bar="5" Pos="56"'
  'Bar="5" Pos="40"'       = 'Bar="5" Pos="60"'
  'Bar="5" Pos="42"'       = 'Bar="5" Pos="62"'
  'Bar="5" Pos="44"'       = 'Bar="6" Pos="2"'
  'Bar="5" Pos="46"'       = 'Bar="6" Pos="4"'
  'Bar="5" Pos="48"'       = 'Bar="6" Pos="8"'
  'Bar="5" Pos="50"'       = 'Bar="6" Pos="10"'
  'Bar="5" Pos="52"'       = 'Bar="6" Pos="14"'
  'Bar="5" Pos="54"'       = 'Bar="6" Pos="16"'
  'Bar="5" Pos="56"'       = 'Bar="6" Pos="20"'
  'Bar="5" Pos="58"'       = 'Bar="6" Pos="22"'
  'Bar="5" Pos="60"'       = 'Bar="6" Pos="26"'
  'Bar="5" Pos="62"'       = 'Bar="6" Pos="28"'
  'Bar="6" Pos="0"'        = 'Bar="6" Pos="32"'
  'EndBar="5" EndPos="0"'  = 'EndBar="5" EndPos="0"'
  'EndBar="5" EndPos="2"'  = 'EndBar="5" EndPos="2"'
  'EndBar="5" EndPos="4"'  = 'EndBar="5" EndPos="6"'
  'EndBar="5" EndPos="6"'  = 'EndBar="5" EndPos="8"'
  'EndBar="5" EndPos="8"'  = 'EndBar="5" EndPos="12"'
  'EndBar="5" EndPos="10"' = 'EndBar="5" EndPos="14"'
  'EndBar="5" EndPos="12"' = 'EndBar="5" EndPos="18"'
  'EndBar="5" EndPos="14"' = 'EndBar="5" EndPos="20"'
  
}
$xmlfile = "1.xml"
$xmlfilenew = "1_new.xml"

$hashValue = @{ }
$hashModified = @{ }
$re = [regex]'(\w+)="([^"]*)"'
$xmldoc = New-Object -TypeName System.Xml.XmlDocument
try {
  $xmldoc.Load($xmlfile)
  foreach ($strKey in $hashAttr.Keys) {
    $strXPath = $strKey -replace '\w+=', '@$&' -replace ' @', ' and @'
    $strValue = $hashAttr.Item($strKey)
    $hashValue.Clear()
    foreach ($reMatch in $re.Matches($strValue)) {
      $hashValue.Add($reMatch.Groups[1].Value, $reMatch.Groups[2].Value)
    }
    if (!$hashModified.ContainsKey($strValue)) {
      [void]$hashModified.Add($strValue, (New-Object System.Collections.ArrayList))
    }
    if (!$hashModified.ContainsKey($strKey)) {
      [void]$hashModified.Add($strKey, (New-Object System.Collections.ArrayList))
    }
    $alDst = $hashModified.Item($strValue)
    $alSrc = $hashModified.Item($strKey)
    foreach ($node in $xmldoc.DocumentElement.SelectNodes(".//Note[$strXPath]")) {
      if (!$alSrc.Contains($node)) {
        foreach ($dicEntry in $hashValue.GetEnumerator()) {
          $node.SetAttribute($dicEntry.Key, $dicEntry.Value)
        }
        [void]$alDst.Add($node)
      }
    }
  }
  $xmldoc.Save($xmlfilenew)
} catch {
  $_ | Out-String | Write-Host -ForegroundColor Red
}[/code]

aducyl 发表于 2020-2-19 11:04

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=226648&ptid=54875]5#[/url] [i]flashercs[/i] [/b]


    大佬牛逼~~~~

aducyl 发表于 2020-2-19 22:23

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=226648&ptid=54875]5#[/url] [i]flashercs[/i] [/b]


这是另一种xml文件,NoteInfo部分的没有问题,可以正常替换
但是图中用红色椭圆标出的部分不知为什么没有被替换掉


[b][color=Blue]————————————————华丽丽的分割线————————————————[/color][/b]


[url=http://www.bathome.net/space.php?uid=79310][b][color=RoyalBlue]flashercs[/color][/b][/url][color=Red]已经私下回复我了[/color]
[i][b][color=Red]将5楼第79行代码里的“Note”改成“*”即可。[/color][/b][/i]


[b][color=Blue]————————————————华丽丽的分割线————————————————[/color][/b]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.