zoomzoomvince zoomzoomvince - 3 months ago 22
PowerShell Question

Powershell - add elements to XML file if

I have an xml file which container provider information. I need to check if there is an "AddressType" defined within each AddressRow. If the AddressRow is defined (one of 3 types - HQ, SUB, MAIN) then all is OK. If there is no an AddressRow present, then I need to add the missing AddressType element and a description to go with it.

This is the sample XML file. Which has got 2 providers shown.

<?xml version="1.0" encoding="UTF-8"?>
<OrganisationUnits>
<OrganisationUnitsRow num="1">
<OrganisationId>001</OrganisationId>
<OrganisationName>Provider 001</OrganisationName>
<Addresses>
<AddressesRow num="1">
<AddressType>HQ</AddressType>
<AddressTypeDesc>Headquarters</AddressTypeDesc>
</AddressesRow>
<AddressesRow num="2">
<MainAddress>N</MainAddress>
<AddressType>SUB</AddressType>
<AddressTypeDesc>Sub Office</AddressTypeDesc>
</AddressesRow>
</Addresses>
</OrganisationUnitsRow>
<OrganisationUnitsRow num="2">
<OrganisationId>002</OrganisationId>
<OrganisationName>Provider 002</OrganisationName>
<Addresses>
<AddressesRow num="1">
<MainAddress>Y</MainAddress>
<NonStandardAddress>
<LocationId>P520851</LocationId>
<PostCode>G20 9RQ</PostCode>
</NonStandardAddress>
</AddressesRow>
<AddressesRow num="2">
<MainAddress>N</MainAddress>
<NonStandardAddress>
<LocationId>P526750</LocationId>
</NonStandardAddress>
</AddressesRow>
</Addresses>
</OrganisationUnitsRow>
</OrganisationUnits>


The first provider has got 2 address rows each with a correct AddressType of SUB and HQ.
The second provider has 2 AddressRows but not AN AddressType defined. Therefore my script should add a default address Type of "DEF" with a description of "Default Address".

<AddressesRow num="1">
<MainAddress>Y</MainAddress>
<NonStandardAddress>
<LocationId>P520851</LocationId>
<PostCode>G20 9RQ</PostCode>
</NonStandardAddress>
<AddressType>DEF</AddressType>
<AddressTypeDesc>Default Address</AddressTypeDesc>
</AddressesRow>


This is my code which does not seem to be adding the new elements.

$Path = "C:\DEV\sandpit\small.xml"
$xml = [xml](Get-Content $path)

$node = $xml.OrganisationUnits.OrganisationUnitsRow.Addresses.AddressesRow

foreach($AddressType in $node)
{

if ($AddressType.'#text' -ne "HQ" -or $AddressType.'#text' -ne "SUB" -or $AddressType.'#text' -ne "MAIN" )
{
$AddType = $xml.CreateElement("AddressType")
$AddType.set_InnerXML("DEF")
$AddTypeDesc = $xml.CreateElement("AddressTypeDesc")
$AddTypeDesc.set_InnerXML("Default Address")

$xml.OrganisationUnits.OrganisationUnitsRow.Addresses.AddressesRow.AppendChild($AddType, $AddTypeDesc)


}
}

$xml.Save($path)


I cant see why its not behaving as expected - its not adding the new elements.

Answer

You're currently testing against the InnerText of the AddressRow node itself rather than each AddressType child node.

You first need to check whether the AddressType node even exists, then look at the text:

foreach($addressRow in $xml.OrganisationUnits.OrganisationUnitsRow.Addresses.AddressesRow)
{
    if(-not $addressRow.Item('AddressType') -or $addressRow.Item('AddressType')."#text" -notin @('HQ','SUB'))
    {
        $newAddressType = $xml.CreateElement('AddressType')
        $newAddressType.InnerText = 'DEF'

        $newAddressTypeDesc = $xml.CreateElement('AddressTypeDesc')
        $newAddressTypeDesc.InnerText = 'Default Location'

        $newAddressType,$newAddressTypeDesc |ForEach-Object {
            $addressRow.AppendChild($_)
        }
    }
}