AndyDrav
AndyDrav

Reputation: 63

Updating XML files using PowerShell

I'm using PowerShell to update an XML directory listing for an application across a number of servers but having an issue making the actual updates. Using the following XML as an example, looking to update the filepaths with qualnas1 to use something like \GlobalNAS...etc and remove the qualnas2 entry.

<?xml version="1.0" encoding="UTF-8" ?>
<directory>
    <filepath>\\qualnas1\library\content</filepath>
    <filepath>\\qualnas2\library\content</filepath>
    <filepath type="sssb">\\qualnas1\SSSB\content</filepath>
</directory>

The filepath node with type=sssb works when I use the $_.InnerText, but can not find a way to update or remove the other nodes. Here is my code:

$DirectoryXMLPath = 'C:\Temp\directory.xml'
if (Test-Path $DirectoryXMLPath)
{
    $DirectoryXML = New-Object XML
    $DirectoryXML.Load($DirectoryXMLPath)
    $DirectoryXML.PreserveWhitespace = $true

    # Find qualnas1 path and replace with GlobalNAS
    $DirectoryXML.directory.filepath | Where-Object { $_ -eq '\\qualnas1\library\content' } | 
        ForEach-Object { $_.InnerText = '\\GlobalNAS\library\content' }

    # Find extraneous library paths and remove them
    $DirectoryXML.directory.filepath.Remove('\\qualnas2\library\content')
#   $DirectoryXML.directory.mountpoint | Where-Object { $_ -eq '\\qualnas2\library\content' } |
#       ForEach-Object { $DirectoryXML.RemoveChild($_) }

    # This line is good!  Need InnerText as attribute type exists
    $DirectoryXML.directory.filepath | Where-Object { $_.InnerText -eq '\\qualnas1\SSSB\content' } | 
        ForEach-Object { $_.InnerText = '\\GlobalNAS\SSSB\content' }
}

If I step through the code using PowerGUI each node is found and the replace/remove is attempted as I'd expect, but either get errors (string to XmlElement conversion) or no errors but no updates either depending on how I do assignment. Anyway to change/remove specific nodes if there are no attributes as in the SSSB example?

Upvotes: 6

Views: 4637

Answers (1)

Andy Arismendi
Andy Arismendi

Reputation: 52597

I would use a little Xpath to get a handle to the XML nodes. To me it's easier than using the properties that PowerShell creates for XML nodes.

# Find qualnas1 path and replace with GlobalNAS
$DirectoryXML.SelectNodes('/directory/filepath') | ? {
        $_.InnerText -eq '\\qualnas1\library\content'
    } | % {
        $_.InnerText = '\\GlobalNAS\library\content'
    }

# Find extraneous library paths and remove them
$DirectoryXML.SelectNodes('/directory/filepath') | ? {
        $_.InnerText -eq '\\qualnas2\library\content'
    } | % {
        $_.ParentNode.RemoveChild($_)
    }

Upvotes: 5

Related Questions