使用PowerShell 4.0向XML添加节点的技术问题求助
向带命名空间的XML添加新节点的解决方案
现有API返回XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AccessPermissions xmlns="http://localhost/RESTApi/v1"> <AccessProfilePermissions/> <ReaderSpecialPermissions/> <RoomZoneSpecialPermissions> <RoomZoneSpecialPermission> <RoomZoneNumber>6</RoomZoneNumber> <AccessWeeklyProfileNumber>1</AccessWeeklyProfileNumber> <ValidFrom>2023-07-13</ValidFrom> </RoomZoneSpecialPermission> </AccessPermissions>
预期结果
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <AccessPermissions xmlns="http://localhost/RESTApi/v1"> <AccessProfilePermissions/> <ReaderSpecialPermissions/> <RoomZoneSpecialPermissions> <RoomZoneSpecialPermission> <RoomZoneNumber>6</RoomZoneNumber> <AccessWeeklyProfileNumber>1</AccessWeeklyProfileNumber> <ValidFrom>2023-07-13</ValidFrom> </RoomZoneSpecialPermission> <RoomZoneSpecialPermission> <RoomZoneNumber>7</RoomZoneNumber> <AccessWeeklyProfileNumber>1</AccessWeeklyProfileNumber> <ValidFrom>2023-07-31</ValidFrom> </RoomZoneSpecialPermission> </AccessPermissions>
当前错误脚本
# API Response to XML Object $xmlObject = [xml]$apiresponse # New Permission in XML Format and conver to XML Object $newxml = "<RoomZoneSpecialPermission><RoomZoneNumber>7</RoomZoneNumber><AccessWeeklyProfileNumber>1</AccessWeeklyProfileNumber><ValidFrom>2023-07-31</ValidFrom></RoomZoneSpecialPermission>" $newPermissionObject = [xml]$newxml # Select RoomZoneSpecialPermissions Node $roomZoneSpecialPermissions = $xmlObject.SelectSingleNode("//a:RoomZoneSpecialPermissions", $xmlObject.DocumentElement.NamespaceURI) # New RoomZoneSpecialPermission Node $newPermissionElement = $xmlObject.CreateElement("RoomZoneSpecialPermission", "http://localhost/RESTApi/v1") # Add Elements to RoomZoneSpecialPermission Node generated above $newPermissionElement.AppendChild($xmlObject.CreateElement("RoomZoneNumber", "http://localhost/RESTApi/v1")).InnerText = "7" $newPermissionElement.AppendChild($xmlObject.CreateElement("AccessWeeklyProfileNumber", "http://localhost/RESTApi/v1")).InnerText = "1" $newPermissionElement.AppendChild($xmlObject.CreateElement("ValidFrom", "http://localhost/RESTApi/v1")).InnerText = "2023-07-31" $roomZoneSpecialPermissions.Trust.FrameworkPolicy.ClaimsProviders.AppendChild($newPermissionElement) $modifiedxml = $xmlObject.OuterXml Write-Output $modifiedxml
遇到的错误
- 调用
AppendChild时出现异常:“要插入的节点来自不同的文档上下文” - 找不到
SelectSingleNode的重载,参数计数为2
修正后的脚本及说明
问题分析
- 命名空间处理错误:
SelectSingleNode的第二个参数需要XmlNamespaceManager对象,而非直接传入命名空间字符串。 - 节点路径错误:最后一行的
$roomZoneSpecialPermissions.Trust.FrameworkPolicy.ClaimsProviders完全不符合原XML结构,应直接对$roomZoneSpecialPermissions调用AppendChild。 - 冗余节点对象:脚本中创建的
$newPermissionObject未使用,还会导致跨文档上下文问题,直接用原XML对象创建节点即可避免。
修正代码
# API Response to XML Object $xmlObject = [xml]$apiresponse # 创建命名空间管理器 $nsManager = New-Object System.Xml.XmlNamespaceManager($xmlObject.NameTable) $nsManager.AddNamespace("a", $xmlObject.DocumentElement.NamespaceURI) # 选中目标父节点RoomZoneSpecialPermissions $roomZoneSpecialPermissions = $xmlObject.SelectSingleNode("//a:RoomZoneSpecialPermissions", $nsManager) # 创建新的RoomZoneSpecialPermission节点(带命名空间) $newPermissionElement = $xmlObject.CreateElement("RoomZoneSpecialPermission", $xmlObject.DocumentElement.NamespaceURI) # 添加子节点并设置文本 $roomZoneNum = $xmlObject.CreateElement("RoomZoneNumber", $xmlObject.DocumentElement.NamespaceURI) $roomZoneNum.InnerText = "7" $newPermissionElement.AppendChild($roomZoneNum) $profileNum = $xmlObject.CreateElement("AccessWeeklyProfileNumber", $xmlObject.DocumentElement.NamespaceURI) $profileNum.InnerText = "1" $newPermissionElement.AppendChild($profileNum) $validFrom = $xmlObject.CreateElement("ValidFrom", $xmlObject.DocumentElement.NamespaceURI) $validFrom.InnerText = "2023-07-31" $newPermissionElement.AppendChild($validFrom) # 将新节点添加到父节点下 $roomZoneSpecialPermissions.AppendChild($newPermissionElement) # 输出修改后的XML $modifiedxml = $xmlObject.OuterXml Write-Output $modifiedxml
简化写法可选
如果觉得逐节点创建麻烦,也可以用ImportNode将外部XML节点导入到当前文档上下文后再添加:
$xmlObject = [xml]$apiresponse $nsManager = New-Object System.Xml.XmlNamespaceManager($xmlObject.NameTable) $nsManager.AddNamespace("a", $xmlObject.DocumentElement.NamespaceURI) $roomZoneSpecialPermissions = $xmlObject.SelectSingleNode("//a:RoomZoneSpecialPermissions", $nsManager) # 定义新节点XML字符串(需包含命名空间) $newPermissionXml = @" <RoomZoneSpecialPermission xmlns="http://localhost/RESTApi/v1"> <RoomZoneNumber>7</RoomZoneNumber> <AccessWeeklyProfileNumber>1</AccessWeeklyProfileNumber> <ValidFrom>2023-07-31</ValidFrom> </RoomZoneSpecialPermission> "@ $newXmlObj = [xml]$newPermissionXml # 导入节点到当前文档上下文(第二个参数为true表示递归导入子节点) $importedNode = $xmlObject.ImportNode($newXmlObj.DocumentElement, $true) # 添加节点 $roomZoneSpecialPermissions.AppendChild($importedNode) $modifiedxml = $xmlObject.OuterXml Write-Output $modifiedxml
内容的提问来源于stack exchange,提问作者Nico
相关产品推荐
相关产品推荐

