zoomzoomvince zoomzoomvince - 3 months ago 42
PowerShell Question

Remove XML Node

I have an XML file which contains a

<Notes>
node that I wish to remove.

<APPOrganisationUnits>
<APPOrganisationUnitsRow num="1">
<OrganisationId>TEST1</OrganisationId>
<APPContactDetails>
<APPContactDetailsRow num="1">
<Notes>Notes 1</Notes>
</APPContactDetailsRow>
<APPContactDetailsRow num="2">
<Notes>Notes 2</Notes>
</APPContactDetailsRow>
<APPContactDetailsRow num="3">
<Notes>Notes 3</Notes>
</APPContactDetailsRow>
</APPContactDetails>
</APPOrganisationUnitsRow>
<APPOrganisationUnitsRow num="2">
<OrganisationId>TEST2</OrganisationId>
<APPContactDetails>
<APPContactDetailsRow num="1">
<Notes>Notes 1</Notes>
</APPContactDetailsRow>
<APPContactDetailsRow num="2">
<Notes>Notes 2</Notes>
</APPContactDetailsRow>
</APPContactDetails>
</APPOrganisationUnitsRow>
</APPOrganisationUnits>


For each instance of the
<notes>
node I just want to remove it. My code this which runs but does not remove the nodes.

$XMLFile = "$Provider_Root\Processing\small.xml"
$xml = [xml](Get-Content $XMLFile)

foreach ($APPContactDetailsRow in $xml.APPOrganisationUnits.APPOrganisationUnitsRow.APPContactDetails) {
if ($APPContactDetailsRow.Item('Notes')) {
$APPContactDetailsRow.RemoveChild($_)
}
}
$xml.Save($XMLFile)
}

Answer

The current object variable ($_) isn't populated in the context of your loop. You need to put the child node into a variable before you can remove it. Also, Just because you name a variable after a particular type of nodes doesn't automagically enumerate the nodes via this variable. You need to actually expand the nodes.

Change this:

foreach ($APPContactDetailsRow in $xml.APPOrganisationUnits.APPOrganisationUnitsRow.APPContactDetails) {
    if ($APPContactDetailsRow.Item('Notes')) {
        $APPContactDetailsRow.RemoveChild($_)
    }
}

into this:

foreach ($APPContactDetailsRow in $xml.APPOrganisationUnits.APPOrganisationUnitsRow.APPContactDetails.APPContactDetailsRow) {
    $n = $APPContactDetailsRow.Item('Notes')
    if ($n) {
        $APPContactDetailsRow.RemoveChild($n)
    }
}

With that said, it'd probably be simpler to select the nodes with an XPath expression and use a pipeline for deleting them:

$xml.SelectNodes('//AppContactDetailsRow/Notes') | ForEach-Object {
    $_.ParentNode.RemoveChild($_)
}
Comments