iOS(iPhone)やApple Watchで溜めているヘルスケアデータを、
再利用するためにデータ出力をしたが、xml形式で使いにくかったのでCSVに変換してみようというお話。
当方環境
- iPhone7 iOS 12.2
- Apple Watch gen3(だった気がする)
やり方
- iPhoneのHealthアプリケーションから、
Export Health Darta
を選択し、zipファイルをエクスポートさせる。
⇨しばらくするとファイルをどうするか聞かれるので、任意の方法でPCに送る
当方はmacでiCloud連携を使用してデスクトップにおきました。
- zipファイルを解凍する
-
ZIPファイルを解凍すると以下のようなディレクトリ構成になっています。
. ├── README.md ├── apple_health_export │ ├── export.xml │ └── export_cda.xml
-
export_cda.xmlは中身がよくわからなかったので無視。
-
- 以下、編集するためのプログラムです。
package main
import (
"encoding/xml"
"io/ioutil"
"log"
"os"
"github.com/gocarina/gocsv"
)
type HealthData struct {
XMLName xml.Name `xml:"HealthData"`
Record []Record
}
type Record struct {
Type string `xml:"type,attr" csv:"type"`
SourceName string `xml:"sourceName,attr" csv:"-"`
SourceVersion string `xml:"sourceVersion,attr" csv:"-"`
Unit string `xml:"unit,attr" csv:"unit"`
CreationDate string `xml:"creationDate,attr" csv:"-"`
StartDate string `xml:"startDate,attr" csv:"startDate"`
EndDate string `xml:"endDate,attr" csv:"endDate"`
Value string `xml:"value,attr" csv:"value"`
}
func main() {
// open xml file.
xmlFile, err := os.Open("./apple_health_export/export.xml")
if err != nil {
log.Fatal(err)
}
defer xmlFile.Close()
// read xml data.
xmlData, err := ioutil.ReadAll(xmlFile)
if err != nil {
log.Fatal(err)
}
// parse xml and export to csv.
csvFile, err := os.Create("./export.csv")
if err != nil {
log.Fatal(err)
}
defer csvFile.Close()
var healthData HealthData
xml.Unmarshal(xmlData, &healthData)
records := healthData.Record
gocsv.MarshalFile(&records, csvFile)
}
ポイント
HealthData内にRecordとして複数データが含まれているデータ構造だったので、
HealthData構造体とRecord構造体を用意しました。
Record構造体から抜き出す項目は csv:"xxx"
として記述し、
抽出不要項目はcsv:"-"
とすることでparserが良い感じに処理してくれます。
改善ポイント
- メモリ消費が非常に大きい
- ファイルサイズが大きいとそれに比例してメモリ使用量が増える
最後に
走り書きですが、とりあえず使えそうなデータが取れたので、
CSVを使って何かできないか試してみたいと思います。