前書き
防災アプリ開発 Advent Calendar 2025の記事にしようと思ったけどちょっと内容が薄いのでいろいろまとめてブログに書きました。
この記事はその一部の詳細です。
気象庁防災情報XMLフォーマット形式電文は種類が多すぎてちょっとでも効率化したいですよね。(ちょっとだけ)効率化、できます。
注意
自分がまだまだ作れてないので間違っているところがあると思います...
いろいろタスクがたまっているので結構雑です。
本編
クラスの生成
気象庁防災情報XMLフォーマット 技術資料を見てみると、解説資料セットの他にXMLスキーマファイル (xsd形式) があります。解説資料を見てXPathかクラスをちまちま作るのもいいですが、名前空間?なにそれおいしいの? だったりで意味不明(というほどでもないが)です。
XMLスキーマファイルはxsd形式で提供されていますが、C#ではXML スキーマ定義ツール (Xsd.exe)があるのでこれを利用することで簡単にクラスが作成できます。
これでOK!あとはコード補完も活用して頑張ろう!と言いたいところですが、仕様的に修正が必要な個所があるので修正していきます。
修正点
namespace、classの付与
最初から付いてたか忘れましたが適当に付けましょう。
+ namespace xxxx//適当なnamespace
+ {
+ public class yyyy//適当なルートクラス
+ {
...
+ }
+ }
警告の無効化
うるさいので、たぶん大丈夫だと信じて消します。
+ #pragma warning disable CS8981 // 型名には、小文字の ASCII 文字のみが含まれています。このような名前は、プログラミング言語用に予約されている可能性があります。
...
+ #pragma warning restore CS8981 // 型名には、小文字の ASCII 文字のみが含まれています。このような名前は、プログラミング言語用に予約されている可能性があります。
Reportクラス名の変更
自動生成のクラスはtype~というようになっています。Reportはデシリアライズの際に使うことになるのでいい感じの名前に変えておきましょう。
- public partial class typereport
+ public partial class C_Report//例
この形式がいいのかは知りません。
Bodyの調整
最も重要です。自動生成では複数のBodyの種類をうまくまとめられていないので修正します。
この場合、参照する際は.Bodyの所を.Body_meteorology1などとすればOKです。
- private System.Xml.XmlElement anyField;
- //...
- [System.Xml.Serialization.XmlAnyElementAttribute()]
- public System.Xml.XmlElement[] Body
- {
- get
- {
- return this.anyField;
- }
- set
- {
- this.anyField = value;
- }
- }
//↑この辺は変更に変更を重ねたので違うかも
+ [System.Xml.Serialization.XmlElementAttribute("Body", Namespace = "http://xml.kishou.go.jp/jmaxml1/body/meteorology1/")]
+ public typeBody Body_meteorology1 { get; set; }
+ //...
+ [System.Xml.Serialization.XmlElementAttribute("Body", Namespace = "http://xml.kishou.go.jp/jmaxml1/body/seismology1/")]
+ public typeBody1 Body_seismology1 { get; set; }
+ //...
+ [System.Xml.Serialization.XmlElementAttribute("Body", Namespace = "http://xml.kishou.go.jp/jmaxml1/body/volcanology1/")]
+ public typeBody2 Body_volcanology1 { get; set; }
float→double
floatになっているので必要に応じてdoubleにします。
勝手に配列になっている所の修正(要検証)
0/1回出現のものでも配列になっているようなので、調整するといいでしょう。私はまだ変えていませんが([0]でゴリ押し)。
以下は変えていたのでなんかエラーがあったかもしれません(適当)。
- private typeWeatherForecastProbability[][] fiftyKtWindProbabilityPartField;
- //...
- public typeWeatherForecastProbability[][] FiftyKtWindProbabilityPart
+ private typeWeatherForecastProbability[] fiftyKtWindProbabilityPartField;
+ ...
+ public typeWeatherForecastProbability[] FiftyKtWindProbabilityPart
controlの日時自動ローカルタイム化
好きなようにしていいですが、ここだけUTCなので自動でローカルタイムに。
- this.dateTimeField = value;
+ this.dateTimeField = value.ToLocalTime();
実装例
ぜんぜんできていないJmaXmlViewer。
var entryXmlString = await client.GetStringAsync(entry.Id);
var serializer_entry = new XmlSerializer(typeof(Utilities.XmlClass_XSD.C_Report));
using var reader_entry = new StringReader(entryXmlString);
var xml = (Utilities.XmlClass_XSD.C_Report?)serializer_entry.Deserialize(reader_entry) ?? throw new Exception("XMLの読み込みに失敗しました。");
その中の生成して修正したクラス。
まとめ
xsdファイルが提供されているので使いましょう。そのままでは利用できないので修正が必要です。どちらにしても作業量はえげつないので頑張りましょう()
なお、どちらにしても仕様違反電文があったらエラーになりかねないので起きないことを祈っておきましょう。