我有一个函数,它返回一个带有各种键的哈希表,其中一个是XML。我还有一些代码旨在在返回此 XML 之前对其进行修改。但是,我遇到了起初似乎是管道污染的问题,但我已将其隔离到 XML 替换代码中。
因此,最初我使用 $result.xml
直接使用返回哈希中的键进行了所有 XML 替换。但是,我已经更改了代码以使用单独的变量,如下所示:
$revisedXml = $result.xml
$oldnode = $revisedXml.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$supersedes']")
$newnode = $temp.xml.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$supersedes']")
$importNode = $revisedXml.ImportNode($newnode, $true)
$oldnode.ParentNode.AppendChild($importNode)
$oldnode.ParentNode.RemoveChild($oldnode)
但是,最后两行中的任何一行都是导致$return
哈希爆炸的原因。这让我想到我想我记得一些关于 XML 通过引用而不是按值的事情,所以我真正做的是直接访问 XML,只是通过一个新的指针,而我正在更改的内容以某种方式炸毁了也引用 XML 的整个哈希表变量。这听起来是对的,还是我已经走错了路?
另外,也许是相关的。我最终要做的是在$result.xml
和不同的$temp.xml
(从不同的文件加载)中搜索特定节点,如果找到,请将$result
中的节点替换为$temp
中的节点。我尝试使用ReplaceChild()
,但这似乎不起作用,可能是PowerShell 2.0问题。
那么,有了这两位数据,是否有更好的方法来修改 XML,有没有办法使其与按值正确传递 XML 的函数一起工作?FWIW,我正在重构以避免我成功使用的全局 XML 变量。我通常不喜欢全局变量,但也许这是我必须使用它们的一种情况?
编辑:因此,试图隔离问题,并遇到新问题。在这里,我尝试在函数中创建两个 XML 变量,将一个变量中的节点替换为另一个变量中的节点并将其传回函数,然后写入控制台以验证结果是否正确(差异是 SilentModeID 应为 9)。问题是这里的两个字符串不起作用。也尝试使用单引号,但仍然抛出错误。在我的真实代码中,我并没有使用字符串,而是从文件中读取XML,但出于讨论的目的,这似乎是更好的方法。那么,第一个新问题,我到底在这里做错了什么字符串?一旦它起作用,我们就可以查看是否以相同的方式将 XML 传回
。function Write-PxXmlToConsole ($xml) {
$stringWriter = New-Object System.IO.StringWriter
$xmlWriter = New-Object System.Xml.XmlTextWriter $stringWriter
$xmlWriter.Formatting = "indented"
$xml.WriteTo($xmlWriter)
$xmlWriter.Flush()
$stringWriter.Flush()
Write-Host $stringWriter.ToString()
}
function Import-PxXml {
$result = @{
success = $true
xml = $null
log = $null
}
[xml]$assets = @"
<?xml version="1.0"?>
<Definitions>
<InstallTypes>
<InstallType id="deployment">
<SilentModeID>1</SilentModeID>
</InstallTypes>
</InstallType>
</Definitions>
"@
[xml]$newAssets = @"
<?xml version="1.0"?>
<Definitions>
<InstallTypes>
<InstallType id="deployment">
<SilentModeID>9</SilentModeID>
</InstallType>
</InstallTypes>
</Definitions>
"@
$nodeName = 'deployment'
$oldnode = $assets.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$nodeName']")
$newnode = $newAssets.selectSingleNode("/Definitions/InstallTypes/InstallType[@id='$nodeName']")
$importNode = $assets.ImportNode($newnode, $true)
$oldnode.ParentNode.AppendChild($importNode)
$oldnode.ParentNode.RemoveChild($oldnode)
$result.xml = $assets
$result.log = 'Crossed Fingers'
return $result
}
$test = Import-PxXml
Write-PxXmlToConsole $test.xml
RemoveChild()
和 AppendChild()
方法返回有问题的子节点,从而污染您的输出。
抑制输出,你会没事的:
$null = $oldnode.ParentNode.AppendChild($importNode)
$null = $oldnode.ParentNode.RemoveChild($oldnode)