Home > other >  Updating xml file with powershell
Updating xml file with powershell

Time:08-20

I'm trying to edit an XML file with Powershell. Specifically, a track in GPX format in which I want to correct the altitude coordinates of certain points, those corresponding to time after a certain moment (the time I changed the batteries to the GPS). This is the script with which I intend to do the update:

$filePath = "c:\users\g\documents\bat\PetroglifosV.gpx"
$xml = [xml] (Get-Content $filePath)
$nodes = $xml.SelectNodes("//trkpt")
# Write-Host "Tratando: " $nodes
foreach ($element in $nodes) {
   Write-Host "Tratando elemento: " $element.ele.InnerText
   if ($element.time.InnerText.Substring(11,5) -gt "08:48") { $element.ele.InnerText = 217   $element.ele.InnerText }
   Write-Host "Tratado elemento: " $element.ele.InnerText
   }
$xml.Save("c:\users\g\documents\bat\petrotemp.txt")

And this is the XML file:

<?xml version="1.0" encoding="UTF-8"?>
<gpx creator="Wikiloc - https://www.wikiloc.com" version="1.1" xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">
  <metadata>
    <name>Wikiloc - Baiona a los petroglifos de Outeiro dos Lameiros</name>
    <author>
      <name>guigargi</name>
      <link href="https://www.wikiloc.com/wikiloc/user.do?id=657054">
        <text>guigargi on Wikiloc</text>
      </link>
    </author>
    <link href="https://www.wikiloc.com/hiking-trails/baiona-a-los-petroglifos-de-outeiro-dos-lameiros-26925951">
      <text>Baiona a los petroglifos de Outeiro dos Lameiros on Wikiloc</text>
    </link>
    <time>2018-07-23T09:55:48Z</time>
  </metadata>
  <trk>
    <name>Baiona a los petroglifos de Outeiro dos Lameiros</name>
    <cmt>
    </cmt>
    <desc>
    </desc>
    <trkseg>
      <trkpt lat="42.117677" lon="-8.847421">
        <ele>-12.431</ele>
        <time>2018-07-23T06:55:22Z</time>
      </trkpt>
      <trkpt lat="42.117649" lon="-8.847403">
        <ele>-12.461</ele>
        <time>2018-07-23T06:55:23Z</time>
      </trkpt>
      <trkpt lat="42.117661" lon="-8.847388">
        <ele>-12.407</ele>
        <time>2018-07-23T06:55:24Z</time>
      </trkpt>
      <trkpt lat="42.117687" lon="-8.847385">
        <ele>-12.408</ele>
        <time>2018-07-23T06:57:09Z</time>
      </trkpt>
      <trkpt lat="42.117593" lon="-8.847370">
        <ele>-12.435</ele>
        <time>2018-07-23T06:57:25Z</time>
      </trkpt>
      <trkpt lat="42.113513" lon="-8.838031">
        <ele>-184.594</ele>
        <time>2018-07-23T09:55:38Z</time>
      </trkpt>
      <trkpt lat="42.113517" lon="-8.838084">
        <ele>-184.520</ele>
        <time>2018-07-23T09:55:48Z</time>
      </trkpt>
    </trkseg>
  </trk>
</gpx>

It seems to me that it does not enter the FOR EACH loop, I guess because the $NODES array has nothing. The SAVE order seems work fine.

Can anyone help me. Thank you

GGG

CodePudding user response:

You are comparing strings against strings, but what you need to do is compare TimeSpan objects against each other.

Try

# load the xml file. This way, you are ensured to get the file encoding correct
$xml = [System.Xml.XmlDocument]::new()
$xml.Load('c:\users\g\documents\bat\PetroglifosV.gpx')

# create a TimeSpan object to match the XML <time> elements against
$compareTime = [TimeSpan]::new(8,48,0)  # Hours, Minutes, Seconds

$nodes = $xml.DocumentElement.trk.trkseg.trkpt
foreach ($element in $nodes) {
   Write-Host "Tratando elemento: $($element.ele)"
   # the dates in the XML are given as UTC, so you probably want ToUniversalTime()
   $time = ([datetime]$element.time).ToUniversalTime().TimeOfDay  # --> convert into a TimeSpan object
   # compare the TimeSpan objects
   if ($time -gt $compareTime) { 
        $value = [double]$element.ele   217
        $element.ele = "$value"
        Write-Host "Tratado elemento: $($element.ele)"
   }
}

$xml.Save('c:\users\g\documents\bat\petrotemp.xml')

CodePudding user response:

Here is similar solution

using assembly System 
using assembly System.Xml.Linq 

$filename = "c:\temp\test.xml"
$xDoc = [System.Xml.Linq.XDocument]::Load($filename)
$root = [System.Xml.Linq.XElement]$xDoc.Root
$ns = [System.Xml.Linq.XNamespace]$root.GetDefaultNamespace()
$times = $root.Descendants($ns   "time")
foreach($time in $times)
{

   $date = [DateTime]$time.Value
   if ($date.TimeOfDay -gt [TimeSpan]::Parse("08:48"))
   {
      $time.Value = (217   $date.Ticks).Value
   }
}
  • Related