Powershell,用于移动XML元素时vs Foreach
我有一个将XML元素从一个位置移动到另一个位置的循环。对于For循环,它可以正常工作,但是对于Foreach循环,它将永远迭代。这只是XMLElement与foreach循环实现的不幸冲突,还是我缺少了更好的实践?我绝对不是System.Xml库的专家 演示脚本 输出Powershell,用于移动XML元素时vs Foreach,xml,powershell,Xml,Powershell,我有一个将XML元素从一个位置移动到另一个位置的循环。对于For循环,它可以正常工作,但是对于Foreach循环,它将永远迭代。这只是XMLElement与foreach循环实现的不幸冲突,还是我缺少了更好的实践?我绝对不是System.Xml库的专家 演示脚本 输出 从快速实验来看,这确实是一个冲突,在试图在循环中修改迭代器的意义上。也就是说,您最初选择的是所有元素,包括目标中的元素。人们会认为这应该是无害的,但显然不是。要证明这一点,请将节点选择更改为: $files = $xmlDoc.S
从快速实验来看,这确实是一个冲突,在试图在循环中修改迭代器的意义上。也就是说,您最初选择的是所有元素,包括目标中的元素。人们会认为这应该是无害的,但显然不是。要证明这一点,请将节点选择更改为:
$files = $xmlDoc.SelectNodes('//dir[@Id="source"]/file')
。。。其中,仅选择源中的那些文件节点。毕竟,不需要包括目标中的那些,因为它们已经在您想要的地方了。通过该更改,代码将按预期执行
下面是另一个可以使用的变体,返回到原始选择器。我只更改了标记为OctorOps的三行以获取节点,然后在单独的步骤中修改XML:
# Reset and try with a foreach loop
$xmlDoc = $xmlDocOriginalValue.Clone()
$files = $xmlDoc.SelectNodes('//file')
$destination = $xmlDoc.SelectSingleNode('//dir[@Id="destination"]')
Write-Host "`nForeach loop"
Write-Host "XML before: $($xmlDoc.OuterXml)"
$i = 0
$list = @() ##############
foreach($file in $files) { $list += $file } ##############
foreach($item in $list) ##############
{
Write-Host ("Iteration "+$i + ", " + $file.OuterXml)
$destination.AppendChild($item) | Out-Null
$i++
}
Write-Host "XML after: $($xmlDoc.OuterXml)"
啊哈,这就清楚了。我很惊讶上一行的查询被循环重新评估,这解释了无限循环。这不是我第一次看到PowerShell违反时间规则;SelectNodes返回的集合与上面创建的$list相比,必须具有某种特殊性。如果我感到好奇,我会审问它。谢谢是的,我很想知道你发现了什么!
$files = $xmlDoc.SelectNodes('//dir[@Id="source"]/file')
# Reset and try with a foreach loop
$xmlDoc = $xmlDocOriginalValue.Clone()
$files = $xmlDoc.SelectNodes('//file')
$destination = $xmlDoc.SelectSingleNode('//dir[@Id="destination"]')
Write-Host "`nForeach loop"
Write-Host "XML before: $($xmlDoc.OuterXml)"
$i = 0
$list = @() ##############
foreach($file in $files) { $list += $file } ##############
foreach($item in $list) ##############
{
Write-Host ("Iteration "+$i + ", " + $file.OuterXml)
$destination.AppendChild($item) | Out-Null
$i++
}
Write-Host "XML after: $($xmlDoc.OuterXml)"