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

如何使用PowerShell定位XML元素并添加带属性的子元素

解决PowerShell定位XML元素并追加子元素的问题

需要给XML中Key属性为ToolSetManager的<Record>元素追加3个带<Path>和<Title>子节点的<ToolSet>节点。以下是正确实现方案:


原XML结构

<?xml version="1.0" encoding="utf-8"?>
<UserPreferences Version="3">
  <Record Key="ProfileManager">
    <Path>C:\Users\bob\AppData\Roaming\Software\21\</Path>
  </Record>
  <Record Key="Measurement Creation Context">
    <SnapOrthogonal>False</SnapOrthogonal>
    <SnapContent>True</SnapContent>
   </Record>
  <Record Key="WebFavoritesList" />
  <Record Key="DefaultsManager" />
  <Record Key="ToolSetManager">
    <ToolSet>
      <Path>Tool Set 1.btx</Path>
      <Title>Tool Set 1</Title>
    </ToolSet>
    <ToolSet>
      <Path>My Tool Set.btx</Path>
      <Title>My Tool Set</Title>
    </ToolSet>
  </Record>
  <Record Key="RecentFileList" />
  <Record Key="TemplateData" />

     .
   </Record>
</UserPreferences>

用户原错误代码

$xml = [xml](Get-Content "$env:appdata\software\21\UserPreferences.xml")

#Loop to find the Element with the Key "ToolSetManager"
#Hopefully there is a simpler/direct way to get here?
$allRecordKeys = $xml.UserPreferences.Record.key

foreach ($Key in $allRecordKeys) {
 if ($Key -eq "ToolSetManager") {

   $newElement1 = $xml.CreateElement("ToolSet")
   $newElement1.SetAttribute("Path", "Null.btx")
   $newElement1.SetAttribute("Title", "Null")

# This is where I can't figure out what should go before the .appendChild...:
   $xml.RevuUserPreferences.Record.ToolSetManager.AppendChild($newElement1)

   $xml.save("$env:appdata\software\21\UserPreferences.xml")
   }
 }

正确实现步骤

1. 快速定位目标节点

不用循环遍历,直接用两种方式快速定位Key="ToolSetManager"的<Record>节点:

# 方式1:XPath直接查询(最快捷)
$targetRecord = $xml.SelectSingleNode("//Record[@Key='ToolSetManager']")

# 方式2:PowerShell属性筛选
$targetRecord = $xml.UserPreferences.Record | Where-Object { $_.Key -eq "ToolSetManager" }

2. 批量创建并追加子元素

注意:原XML中<Path>和<Title>是<ToolSet>的子节点,不是属性,需修正创建逻辑:

# 定义要添加的3组ToolSet数据
$newToolSets = @(
    @{ Path = "New Tool Set 1.btx"; Title = "New Tool Set 1" },
    @{ Path = "New Tool Set 2.btx"; Title = "New Tool Set 2" },
    @{ Path = "New Tool Set 3.btx"; Title = "New Tool Set 3" }
)

foreach ($ts in $newToolSets) {
    # 创建ToolSet父节点
    $toolSetNode = $xml.CreateElement("ToolSet")
    
    # 创建Path子节点并赋值
    $pathNode = $xml.CreateElement("Path")
    $pathNode.InnerText = $ts.Path
    $toolSetNode.AppendChild($pathNode) | Out-Null
    
    # 创建Title子节点并赋值
    $titleNode = $xml.CreateElement("Title")
    $titleNode.InnerText = $ts.Title
    $toolSetNode.AppendChild($titleNode) | Out-Null
    
    # 将ToolSet节点追加到目标Record下
    $targetRecord.AppendChild($toolSetNode) | Out-Null
}

3. 保存修改后的XML

$xml.Save("$env:appdata\software\21\UserPreferences.xml")

完整正确代码

# 加载XML文件
$xmlPath = "$env:appdata\software\21\UserPreferences.xml"
$xml = [xml](Get-Content $xmlPath)

# 定位目标Record节点
$targetRecord = $xml.SelectSingleNode("//Record[@Key='ToolSetManager']")

# 定义要添加的3组ToolSet数据
$newToolSets = @(
    @{ Path = "New Tool Set 1.btx"; Title = "New Tool Set 1" },
    @{ Path = "New Tool Set 2.btx"; Title = "New Tool Set 2" },
    @{ Path = "New Tool Set 3.btx"; Title = "New Tool Set 3" }
)

# 批量创建并追加子元素
foreach ($ts in $newToolSets) {
    $toolSetNode = $xml.CreateElement("ToolSet")
    
    $pathNode = $xml.CreateElement("Path")
    $pathNode.InnerText = $ts.Path
    $toolSetNode.AppendChild($pathNode) | Out-Null
    
    $titleNode = $xml.CreateElement("Title")
    $titleNode.InnerText = $ts.Title
    $toolSetNode.AppendChild($titleNode) | Out-Null
    
    $targetRecord.AppendChild($toolSetNode) | Out-Null
}

# 保存修改
$xml.Save($xmlPath)

关键修正说明

  • 原代码错误将<Path>和<Title>当成属性处理,实际是子节点,需用CreateElement创建并设置InnerText。
  • 用XPath或Where-Object直接筛选目标节点,避免无效遍历,逻辑更简洁可靠。
  • 修正了原代码中错误的节点引用$xml.RevuUserPreferences,对应XML根节点UserPreferences。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:50:07