【问题标题】:Replace content of an XML based on a lookup table in powershell根据 powershell 中的查找表替换 XML 的内容
【发布时间】:2020-03-13 20:59:58
【问题描述】:

我有一个 XML 文件,其中包含一些需要替换的特定关键字,这是一个示例:

    <?xml version="1.0" encoding="utf-8"?>
<!--Exported at 23-09-2019 10:01:23-->
<DEFTABLE xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Folder.xsd">
    <SMART_FOLDER JOBISN="1" APPLICATION="6261" SUB_APPLICATION="R001J_CMNOK" JOBNAME="6261_R001J_CMNOK" DESCRIPTION="Snapshot des jobs not ok de control-m ds intraprd2" >
        <JOB JOBISN="2" APPLICATION="6261" SUB_APPLICATION="R001J_CMNOK" MEMNAME="R010J.BAT" JOBNAME="6261R001J010J_CMNOK" DESCRIPTION="[07:00] Chargement job ended_notok" CREATED_BY="Graf">
            <VARIABLE NAME="%%LIBMEMSYM" VALUE="%%VG_LIBMEMSYM./CTM.var" />
            <RULE_BASED_CALENDARS NAME="*" />
        </JOB>
        </SMART_FOLDER>
</DEFTABLE>

我需要将“Recette”替换为“Production”,将“6261_R001J_CMNOK”替换为“6261_P001J_CMNOK”,并将新的 XML 写入我之前创建的文件的副本中,如下所示:

$CreateFileName = $($OriginalXMLFilePath -replace ".{4}$") + "_" + $(Get-Date -UFormat "%Y-%m-%d_%H%M%S") + ".xml"
$CopyFile = Copy-Item $OriginalXMLFilePath -Destination $CreateFileName -Force
# New file name is 6261_XML_2019-11-18_135100.xml

我做了以下变量:

$A_Lookup = @("Recette","6261_R001J_CMNOK")
$B_Replace = @("Production", "6261_P001J_CMNOK")

这是我替换 XML 的其余代码:

$Read = Get-Content -Path $OriginalXMLFilePath
for ($i = 0; $i -lt $A_Lookup.length; $i++) {
    $Read = $Read -replace $A_Lookup[$i], $B_Replace[$i]
}
Remove-Item -Path $OriginalXMLFilePath -Force 
Add-Content -Path $OriginalXMLFilePath -Value $Read -Force

问题是,@( 之后大约有 25 多个项目,当我们需要在那里添加更多内容时,这并不是很优化。所以我决定改为制作一个查找表:

$lookupTable = @{
    "Recette" = "Production"
    "6261_R001J_CMNOK" = "6261_P001J_CMNOK"
}

但现在我的主要问题是我的代码中将用$A_Lookup 替换为$B_Replace 的部分不再起作用了。我在 this page 上尝试了“解决方案 4”以及 Stack Overflow 周围的其他解决方案,但没有一个真正适合我。最阻碍我的是我似乎无法将任何内容写入新的 XML 文件。

我在最新版本的 PowerShell 上运行。

【问题讨论】:

  • 不要对这样的操作使用字符串替换。将文件读入 XML 对象并使用 XPath 表达式来选择要替换其值的属性。
  • 一般来说,我会在 XML 文件上使用文本替换,而是将 XML 文档作为 XML 文档进行处理,参见例如How to change the value of XML Element attribute using PowerShell?,或更常见的:Calling XMLDocument Methods in PowerShell
  • @AnsgarWiechers 感谢您的回答,我是初学者,所以我必须知道如何做到这一点。这是你的意思吗 ? docs.microsoft.com/en-us/powershell/module/…
  • Select-Xml 最适合从 XML 读取数据,但是您想修改节点,因此您应该使用 XML 对象的 SelectNodes() 方法(请参阅 iRon 发布的第一个链接,或者执行在 SO 上搜索 [xml] 和 selectnodes)。
  • 好的,非常感谢,我会尝试使用它并报告!

标签: xml powershell powershell-2.0 powershell-3.0 powershell-4.0


【解决方案1】:

您可以按如下方式分解您的任务:

  • 发现所有具有属性的 XML 节点
  • 对于每个这样的节点:
    • 检查每个属性的值
    • 如果当前值作为查找表中的键存在,请将其替换
$LookupTable = @{
  "Recette" = "Production"
  "6261_R001J_CMNOK" = "6261_P001J_CMNOK"
}

$Document = [xml](Get-Content -Path $OriginalXMLFilePath)

# Let's find all nodes that have any attributes
$NodeList = $Document |Select-Xml -XPath '//*[@*]'

# iterate over the nodes, and replace all relevant attribute values
foreach($Node in $NodeList.Node) {
  foreach($Attribute in $Node.Attributes) {
    if($LookupTable.ContainsKey($Attribute.Value)){
      $Attribute.Value = $LookupTable[$Attribute.Value]
    }
  }
}

# save the document
$CreateFileName = $($OriginalXMLFilePath -replace ".{4}$") + "_" + $(Get-Date -UFormat "%Y-%m-%d_%H%M%S") + ".xml"
$Document.Save((Resolve-Path $CreateFileName).ProviderPath)

【讨论】:

    猜你喜欢
    • 2021-02-16
    • 2013-11-26
    • 2019-07-07
    • 1970-01-01
    • 2016-06-08
    • 2012-12-30
    • 2011-10-31
    • 1970-01-01
    • 2012-02-14
    相关资源
    最近更新 更多