0

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

2 Answers 2

1

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')
Sign up to request clarification or add additional context in comments.

3 Comments

Perfect! It works very fine.
@GGG Thanks for the feedback. You may want to consider marking the question 'done' (see the tour), so others with a similar question may also benefit
I thank you again your comment. I hope to do things well next time.
1

Here is similar solution

using assembly System 
using assembly System.Xml.Linq 

$inputFilename = "c:\temp\test.xml"
$outputFilename = "c:\temp\test1.xml"
$xDoc = [System.Xml.Linq.XDocument]::Load($inputFilename)
$root = [System.Xml.Linq.XElement]$xDoc.Root
$ns = [System.Xml.Linq.XNamespace]$root.GetDefaultNamespace()
$trkpts = $root.Descendants($ns + "trkpt")
#date in ZULU time.  Date is not important, only time of day
$timeOfDay = [DateTime]::Parse("1900-01-01T08:48:00Z").TimeOfDay

foreach($trkpt in $trkpts)
{
   $time = $trkpt.Element($ns + "time")
   $date = [DateTime]$time.Value
   if($date.TimeOfDay -gt $timeOfDay)
   {
      $ele = $trkpt.Element($ns + "ele")
      $oldValue = [decimal]$ele.Value
      $ele.Value = (217 + $oldValue)

   }
}
$xDoc.Save($outputFilename)

9 Comments

I suppose this solution could work as well but there are two issues that don't fit what I need: 1. Is not the time that must be modified when it is greater than 8:48 but the altitude (node "ele") 2. I don't see how I should do to save the modified data. I've tried xDoc.Save but it doesn't seem right. Anyway, thank you very much for your input.
I update code and now works. To be consistent, your input time is in Zulu so the time of day you compare should also be in Zulu. So I changed 8:48 to 4:48. Converting to Universal time like Theo did is not consistent.
Now it works as expected, although I had to put 9:48 in the $timeOfDay variable (not 8:48 or 4:48). I can't explain why I needed to make that adjustment. I'm not qualified to judge the consistency of Theo's solution. But I can say that both solutions worked perfectly for me. Thanks again. GGG
Try changing year to 2000. Day Light Savings Time probably didn't exist in 1900.
I've tried year to 2000-01-01 with the same results: I need to set time to 09:48. If I set date/time to 2018-07-23T08:48:00Z it works fine.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.