Skip to main content

Examples on how to update an XML file using PowerShell.

---
title: Update XML Files Using PowerShell
author: Sonam Rastogi
date: May 14, 2014
source: https://blogs.msdn.microsoft.com/sonam_rastogi_blogs/2014/05/14/update-xml-file-using-powershell/
notoc: false
---

There are many blogs on Internet already speaking about updating XML files in
PowerShell, but I felt need of one consolidated blog where complex XML files can
also be updated with long complex Hierarchy of XML nodes and attributes.

Below is an XML example which we will try in this blog to update at various
level of node Hierarchy.

```xml
<?xml version="1.0" encoding="utf-8"?>
<Data version="2.0">
  <Roles>
    <Role Name="ManagementServer" Value="NewManagementServer" />
    <Role Name="ADServer" Value="NewADServer" />
    <Role Name="ADServer" Value="NewADServer" />
  </Roles>
  <SQL>
    <Instance Server="NewSQLServer" Instance="MSSQLSERVER" Version="SQL Server 2012">
      <Variable Name="SQLAdmin" Value="Domain\NewSQlAdmin" />
      <Variable Name="SQLUser" Value="domain\sqluser" />
    </Instance>
```

We will target to update Roles, Variables and VMName, Subject etc. in this XML
file. Below are the steps given separately on how we can update and add nodes
and their attributes at various levels.

1. **Define the variables** which are required to be modified:

    ```powershell
    $path = 'C:\Users\sorastog\Desktop\blog\Variable.xml'

    $ManagementServer = 'NewManagementServer'
    $SQLServer = 'NewSQLServer'
    $SQLAdmin = 'Domain\NewSQlAdmin'
    $DNSServerVMName = 'NewDNSServer'
    $NewNumber = 'NewContactNumber'
    ```

2. **Reading the content** of XML file.

    ```powershell
    $xml = (Get-Content $path)
    ```

3. **Reading List of Subject:** Read Child Tags of Course Node

    ```powershell
    $xml.Data.Course.Subject
    ```

4. **Update 'ManagementServer':** Changing Attribute value of node at level 3 based
   on 'Name' attribute on same level.

    ```powershell
    $node = $xml.Data.Roles.Role | where {$_.Name -eq 'ManagementServer'}
    $node.Value = $ManagementServer
    ```

5. **Update 'SQLServer':** Changing Attribute value of node at level 3.

    ```powershell
    $node = $xml.Data.SQL.Instance
    $node.Server = $SQLServer
    ```

6. **Update 'SQLAdmin':** Changing Attribute value of node at level 4 based on
   'Name' attribute on same level.

    ```powershell
    $node = $xml.Data.SQL.Instance.Variable | where {$_.Name -eq 'SQLAdmin'}
    $node.Value = $SQLAdmin
    ```

7. **Update 'DNSServerVM':** Changing Attribute value of node at level 4 based
   on 'VMType' attribute at above level.

    ```powershell
    $node = $xml.Data.VMs.VM | where {$_.Type -eq 'DNSServerVM'}
    $node.VMName = $DNSServerVMName
    ```

8. **Update Subject Maths:** Update Child nodes based on 'Text' property where
   no attribute is available to differentiate.

    ```powershell
    $node = $xml.Data.Course.ChildNodes
    foreach($subject in $node)
    {
        if ($subject.'#text' -eq "Maths")
        {
            $newChild = $xml.CreateElement("Subject")
            $newChild.set_InnerXML("History")
            $xml.Data.Course.ReplaceChild($newChild, $subject)
        }
    }
    ```

9. **Update Subject Science:** Update Child node based on position of Child node

    ```powershell
    $node = $xml.Data.Course.ChildNodes
    $newChild = $xml.CreateElement("Subject")
    $newChild.set_InnerXML("Computers")
    $xml.Data.Course.ReplaceChild($newChild, $node.Item(1))
    ```

10. **Adding Role:** Adding New Node in XML Hierarchy

    ```powershell
    $newRole = $xml.CreateElement("Role")
    $xml.Data.Roles.AppendChild($newRole)
    ```

11. **Adding 'Name' and 'Value' attributes to Role node:** Adding Attributes to
    XML node

    ```powershell
    $newRole.SetAttribute("Name","ADServer");
    $newRole.SetAttribute("Value","NewADServer");
    ```

12. **Updating Contact Number** when Type is Mobile

    ```powershell
    $allContactsNodes = $xml.Data.AllContacts.Contact
    foreach($node in $allContactsNodes)
    {
       if($node.ContactType.Type -eq 'Mobile')
       {
           $updateNode = $node.Details
           $updateNode.Number = $NewNumber
           break
       }
    }
    ```

13. **Saving changes** to XML file.

    ```powershell
    $xml.Save($path)
    ```

**The final PowerShell script looks like this:**

```powershell
$path = 'C:\Users\sorastog\Desktop\Variable.xml'

$ManagementServer = 'NewManagementServer'
$SQLServer = 'NewSQLServer'
$SQLAdmin = 'Domain\NewSQlAdmin'
$DNSServerVMName = 'NewDNSServer'
$NewNumber = 'NewContactNumber'

$xml = (Get-Content $path)

$xml.Data.Course.Subject

$node = $xml.Data.Roles.Role | where {$_.Name -eq 'ManagementServer'}
$node.Value = $ManagementServer

$node = $xml.Data.SQL.Instance
$node.Server = $SQLServer

$node = $xml.Data.SQL.Instance.Variable | where {$_.Name -eq 'SQLAdmin'}
$node.Value = $SQLAdmin

$node = $xml.Data.VMs.VM | where {$_.Type -eq 'DNSServerVM'}
$node.VMName = $DNSServerVMName

$node = $xml.Data.Course.ChildNodes
foreach($subject in $node)
{
   if ($subject.'#text' -eq 'Maths')
   {
       $newChild = $xml.CreateElement("Subject")
       $newChild.set_InnerXML("History")
       $xml.Data.Course.ReplaceChild($newChild, $subject)
    }
}

$node = $xml.Data.Course.ChildNodes
$newChild = $xml.CreateElement("Subject")
$newChild.set_InnerXML("Computers")
$xml.Data.Course.ReplaceChild($newChild, $node.Item(1))

$newRole = $xml.CreateElement("Role")
$xml.Data.Roles.AppendChild($newRole)

$newRole.SetAttribute("Name","ADServer");
$newRole.SetAttribute("Value","NewADServer");

$allContactsNodes = $xml.Data.AllContacts.Contact
foreach($node in $allContactsNodes)
{
   if($node.ContactType.Type -eq 'Mobile')
   {
       $updateNode = $node.Details
       $updateNode.Number = $NewNumber
       break
   }
}

$xml.Save($path)
```

You can create variable for old and new subjects to be replaced and created
respectively.

We also need to consider situations where the specified node is not found or the
given attribute value is not present. We can always use the `try-catch` error
handling approach in such scenarios, an example would be:

```powershell
$node = $xml.Data.Roles.Role | where {$_.Name -eq 'ManagementServer'}
if ($node -eq $null)
{
    Write-Host "The Role 'ManagementServer' with Attribute 'Name' was not found"
}
else
{
    $node.Value = $ManagementServer
}
```

Hope this will help you to update even complex XML files with multiple nodes and
complex Hierarchy. If there are some XML nodes that you would like to update and
the category is not included in this blog, please reply to this post and I will
add it.