Search code examples
xmlpowershellnodes

Having trouble figuring out how to change XML node value generated by PowerShell script


I've been dabbling with PowerShell for a few years, but I've never dealt with XML and I'm having a difficult time trying to find a solution to a problem I'm seeing. I've read thru countless threads on various forums and I think I admittedly just don't understand enough about what I'm trying to accomplish, nor what other people out there are explaining in other threads.

I'm working on a PowerShell script that someone else wrote, that primarily captures table data, and exports it to an XML file. The table data that is being exported is usable in its current state, but for some values that are NOT derived from tables, I need to find a simple means of changing the name of the XML node.

My PS script example is this:

$StartDate = [Management.ManagementDateTimeConverter]::ToDateTime($SYSINFO.LastBootUpTime)
$StartDate = "{0:G}" -F $StartDate
$EndDate = "{0:G}" -F (Get-Date)
$UPTIME = New-TimeSpan -Start $StartDate -End $EndDate
# Format Uptime for "DD:HH:MM:SS.MMMM"
$DispTime = "{0:G}" -F $UPTIME
# Remove .MMMM (Milliseconds)
$DispTime = $DispTime.Split('.')[0]
$DispTime = "$DispTime"

$DispTime | ConvertTo-XML -As String | Out-File -LiteralPath (C:\Scripts\ + "Uptime_Status.xml")

My XML output ends up looking like this:

<?xml version="1.0" encoding="utf-8"?>
<Objects>
  <Object Type="System.String">0:06:56:39</Object>
</Objects>

What I'm needing to do is change the <Object Type="System.String"> tag to something else, such as <UPTIME>0:06:56:39</UPTIME>, or perhaps even <Object Type="System.String" Name="Uptime">0:06:56:39</Object>

The goal is to differentiate the name of the node from the other XML tags that will like identical to this when I use non-table data. I also see the possibility of needing to do this repetitively, so was wondering if there may also perhaps be an option just utilize the value of a PS variable as the XML node name, throughout the entire XML file, automatically. So for example, if I'm working with 20 pieces of data and I perhaps tag the data of one of the value that is to be captured into the XML, as $DispTime, maybe I can also have another variable like $DispTime_NodeName = "Uptime", and then the resulting XML could just be: <Uptime>0:06:56:39</Uptime>. So basically the PS script would have to find the matching variable name that includes "_NodeName", and then use THAT value as the XML node name. Am I crazy? Is this impossible? Am I over-thinking this?

Thanks so much to anyone that is willing to help.... I'd greatly appreciate any solid help I can get. Just keep in mind, I'm still very much a novice at this :) Haha


Solution

  • For the simple example in your question, you can create your own XML document from scratch:

    $xmlDoc = [xml]::new()
    
    # Add declaration
    [void]$xmlDoc.AppendChild($xmlDoc.CreateXmlDeclaration('1.0', 'utf-8', $null))
    
    # Add <root> node to document
    $root = $xmlDoc.AppendChild($xmlDoc.CreateElement('root'))
    
    # Add <uptime> node to <root>
    $uptime = $root.AppendChild($xmlDoc.CreateElement('uptime'))
    
    # Set inner text value on <uptime> node
    $uptime.InnerText = $DispTime
    
    # Save document
    $xmlDoc.Save((Join-Path C:\Scripts "Uptime_Status.xml"))
    

    If you want a nicer way of authoring XML documents, the Xml module off of PowerShell Gallery might do the trick:

    Install with:

    Install-Module Xml
    

    Then:

    Import-Module Xml
    
    $doc = New-XDocument root -Version 1.0 -Encoding utf-8 {
        New-XElement uptime {
          $DispTime
        }
    }
    
    $doc.Save((Join-Path C:\Scripts "Uptime_Status.xml"))