ゆるく楽しむプログラミング

GPXファイルの標高データを書き換える

目的なんかは実行ファイルの配布ページを参照

GPXファイルはGPSの軌跡情報を記録したXML形式のファイルです。
XMLとは何ぞやは「XMLとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典」あたりを見てください。
XMLの説明が主題ではないので割愛します。

画面を作ります

最初に表示されるFormのデザイン画面でForm上にアイテムを置いて画面を作ります。
リストからアイテムを選んでForm上に配置するだけの簡単なお仕事です。


配置したアイテムのプロパティを設定します。
アイテムをクリックして表示されるプロパティタブの項目を設定します。
(Name)はプログラムからアイテムを操作するためのインスタンス名(変数名のようなもの)です。
この例では文字を表示するだけで入力・編集はできないように ReadOnly を設定しています。


ボタンなどに表示するテキスト、入力枠に入力した文字も同じですが Text に設定設定します。
この例では文字を大きくしたいので Fonr を MS UI Gothicフォントの20ポイントに設定しています。


ボタンをクリックしたときの動作をプログラミングします

この例で操作するアイテムは
 1) オリジナルGPX Fileを選択する[...]ボタン
 2) 変換操作を実行する[変換実行]ボタン
の二つです。

各々のボタンをクリックすると処理メソッドの雛形が作られます。
この例では プロパティタブの(Name)にFileSelectと名前を設定したボタンがクリックされたときの動作を記述するメソッドが表示されています。
Private Sub FileSelect_Click(sender As Object, e As EventArgs) Handles FileSelect.Click

End Sub

ココにファイルチューザー(ファイルを選ぶダイアログ)を表示し、選んだファイルのファイル名を上でInputFileNameと(Name)を設定したアイテムに表示する処理を書きます。
※ついでに変換後のファイル名を変換後のファイル名 OutputFileNameaアイテムに表示します。
Private Sub FileSelect_Click(sender As Object, e As EventArgs) Handles FileSelect.Click
  ’ofd = Open File Dialogの略と思ってください。
  ' この辺りはお約束なので使いまわしできます。

  Dim ofd As New OpenFileDialog()
  ofd.Filter = "GPXファイル(*.gpx)|*.gpx"
  ofd.Title = "GPXファイルを選択してください"
  ofd.FilterIndex = 1
  ofd.RestoreDirectory = True
  ofd.CheckPathExists = False

  If ofd.ShowDialog() = DialogResult.OK Then
    InputFileName.Text = ofd.FileName
    ' 変換後のファイル名は末尾にNEを付け足す。
    Dim fileNE As String = Strings.Left(ofd.FileName, ofd.FileName.Length - 4) & "NE.gpx"
    OutputFileName.Text = fileNE
  End If

End Sub

[変換実行]ボタンをクリックすると同じように処理メソッドの雛形が作られます。
プロパティタブの(Name)にExecと名前を設定したのでメソッドの名前は Exec_Click になります。
ここからGPXファイルを書き換えるプログラムの本体を呼び出します。
Private Sub Exec_Click(sender As Object, e As EventArgs) Handles Exec.Click

  ' フォームの値を取得:直接指定でも良い気がする
  Dim inFileName As String = InputFileName.Text
  Dim outFileName As String = OutputFileName.Text
  Dim mode As Integer = Elevation.SelectedIndex ' 0 - 0m変換 1-削除

  ' 入力ファイルが存在するかチェック
  If Not My.Computer.FileSystem.FileExists(inFileName) Then
    MessageBox.Show("参照不能なファイルが指定されました。" & vbCrLf & "変換を実行できません。")
    Exit Sub
  End If

  ' 出力ファイルが存在するか(上書き)チェック
  If My.Computer.FileSystem.FileExists(outFileName) Then
    If MessageBox.Show(outFileName & vbCrLf & "は存在します。上書きしますか?", "上書き確認", MessageBoxButtons.YesNo) = DialogResult.No Then
      Exit Sub
    End If
  End If

  ' 変換実行
  GPXChange(inFileName, outFileName, mode)

End Sub

GPXファイルを書き換える処理本体をプログラミングします

XMLの操作自体はXmlDocumentクラスを使っているだけなので何という事もありません。
ツリー状になっているXMLファイルの全部の枝を辿るために再帰呼び出しという技法(?)を使っています。
CheckNode( )メソッドの中からCheckNode( )を、つまり自分自身を呼び出す方法で木構造になっているデータ、例えばハードディスクのフォルダとかを順に操作する時によく使う方法です。
Public Sub GPXChange(inFile As String, outFile As String, mode As Integer)
  ' XMLを扱うためのオブジェクトを宣言
  Dim xmlDoc As New XmlDocument()

  ' XMLを読み込み
  xmlDoc.Load(inFile)

  Dim node As XmlNode = xmlDoc.DocumentElement 'XMLドキュメントからルート要素を取り出す
  ' チャイルドノードを順番に操作するので処理を分けて再帰呼び出しにする。
  CheckNode(node,mode)

  ' 処理したXMLを書込み
  xmlDoc.Save(outFile)
End Sub

Private Sub CheckNode(parentNode As XmlNode, mode As Integer)

  ' チャイルドノードを順番にチェック
  For Each node As XmlNode In parentNode.ChildNodes
    If node.Name = "ele" Then
      If mode = 0 Then ' 0-0mに変更 1-削除
        node.InnerText = "0"
      Else
        parentNode.RemoveChild(node) ' ノードを削除
      End If
    Else
      ' トラック名を-NEを付け足した名称に変更
      If parentNode.Name = "trk" And node.Name = "name" Then
        node.InnerText &= "-NE"
      End If

      ' ノードのチャイルドノードをチェック
      If node.HasChildNodes Then
        CheckNode(node,mode)
      End If
    End If
  Next

End Sub

完成

と言う感じで、フォームをデザインしてボタンをクリックすると出てくる雛形の中身を埋めていけばWindowsアプリケーションが出来上がります。
プログラマ責任部分(自分でプログラムを書かなければならない部分)が少ないので割と楽に作れます。

実際にはもうちょっと使い易いように手を加えています。
実行中のカーソルの形を変えたりとか、ボタンを二重に押せないようにグレーアウトしたりとか。
そのあたりはプログラムの本質的な問題ではないので割愛します、色々試してみてください。

完成したプログラム(ソースコードと実行ファイル)はコチラ