PowerShell生成XML时无法添加嵌套param元素的问题排查
问题描述
编写PowerShell脚本生成XML时,期望<constructor>元素内包含<param name='loggerService'/>,但实际生成的XML中<constructor>为空,且运行脚本时报错:You cannot call a method on a null-valued expression。
期望生成的XML
<?xml version="1.0" encoding="utf-8"?> <configuration> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <container> <register name="NoteRecycler" type="StrongPoint.SelfCheckout.Cash.ICashDevice, StrongPoint.SelfCheckout.Cash" mapTo="StrongPoint.Devices.MeiBnr.MeiBnrRecycler, StrongPoint.Devices.MeiBnr"> <lifetime type="singleton" /> <constructor> <param name="loggerService" /> </constructor> </register> </container> </unity> </configuration>
实际生成的XML
<?xml version="1.0" encoding="utf-8"?> <configuration> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <container> <register name="NoteRecycler" type="StrongPoint.SelfCheckout.Cash.ICashDevice, StrongPoint.SelfCheckout.Cash" mapTo="StrongPoint.Devices.MeiBnr.MeiBnrRecycler, StrongPoint.Devices.MeiBnr"> <lifetime type="singleton" /> <constructor /> </register> </container> </unity> </configuration>
报错信息
You cannot call a method on a null-valued expression. At C:\Install\TestUpdater\Test.ps1:140 char:5 + $paramChild = $xml.configuration.unity.container.register.constru ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull You cannot call a method on a null-valued expression. At C:\Install\TestUpdater\Test.ps1:141 char:5 + $paramChild.SetAttribute('name', 'loggerService') + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
脚本代码
$newRegisterNode = $xml.CreateElement("register", $xml.configuration.unity.container.NamespaceURI) $cashConfChild = $xml.configuration.unity.container.AppendChild($newRegisterNode) $cashConfChild.SetAttribute('name', 'NoteRecycler') $cashConfChild.SetAttribute('type', 'StrongPoint.SelfCheckout.Cash.ICashDevice, StrongPoint.SelfCheckout.Cash') $cashConfChild.SetAttribute('mapTo', 'StrongPoint.Devices.MeiBnr.MeiBnrRecycler, StrongPoint.Devices.MeiBnr') $newLifetimeNode = $xml.CreateElement("lifetime", $xml.configuration.unity.container.NamespaceURI) $lifetimeChild = $xml.configuration.unity.container.register.AppendChild($newLifetimeNode) $lifetimeChild.SetAttribute('type', 'singleton') $newConstructorNode = $xml.CreateElement("constructor", $xml.configuration.unity.container.NamespaceURI) $constructorChild = $xml.configuration.unity.container.register.AppendChild($newConstructorNode) $newParamNode = $xml.CreateElement("param", $xml.configuration.unity.container.NamespaceURI) $paramChild = $xml.configuration.unity.container.register.constructor.AppendChild($newParamNode) $paramChild.SetAttribute('name', 'loggerService')
问题原因
报错核心是$xml.configuration.unity.container.register无法正确定位到刚创建的<register>节点:
- 若容器中存在多个
<register>节点,直接通过register属性访问会返回节点集合而非单个节点,导致后续调用方法失败。 - 刚创建的
<register>节点已通过$cashConfChild变量保存,无需重新从DOM路径查找,路径查找可能因DOM更新延迟或节点匹配问题返回null。
修复后的脚本代码
$newRegisterNode = $xml.CreateElement("register", $xml.configuration.unity.container.NamespaceURI) $cashConfChild = $xml.configuration.unity.container.AppendChild($newRegisterNode) $cashConfChild.SetAttribute('name', 'NoteRecycler') $cashConfChild.SetAttribute('type', 'StrongPoint.SelfCheckout.Cash.ICashDevice, StrongPoint.SelfCheckout.Cash') $cashConfChild.SetAttribute('mapTo', 'StrongPoint.Devices.MeiBnr.MeiBnrRecycler, StrongPoint.Devices.MeiBnr') # 直接使用已创建的register节点添加lifetime子节点 $newLifetimeNode = $xml.CreateElement("lifetime", $xml.configuration.unity.container.NamespaceURI) $lifetimeChild = $cashConfChild.AppendChild($newLifetimeNode) $lifetimeChild.SetAttribute('type', 'singleton') # 直接使用已创建的register节点添加constructor子节点 $newConstructorNode = $xml.CreateElement("constructor", $xml.configuration.unity.container.NamespaceURI) $constructorChild = $cashConfChild.AppendChild($newConstructorNode) # 直接使用已创建的constructor节点添加param子节点 $newParamNode = $xml.CreateElement("param", $xml.configuration.unity.container.NamespaceURI) $paramChild = $constructorChild.AppendChild($newParamNode) $paramChild.SetAttribute('name', 'loggerService')
说明
修复后的代码全程使用创建节点时返回的变量($cashConfChild、$constructorChild)操作子节点,避免了DOM路径查找的不确定性,确保节点层级正确,能成功生成包含<param>元素的<constructor>节点。
内容的提问来源于stack exchange,提问作者Kaur16
相关产品推荐
相关产品推荐

