📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| 18行目: | 18行目: | ||
これにより、複雑なXML処理も直感的に記述することが可能になる。<br> | これにより、複雑なXML処理も直感的に記述することが可能になる。<br> | ||
<br> | <br> | ||
※注意<br> | <u>※注意</u><br> | ||
大きなファイルを扱う場合のメモリ使用量や外部からのXMLインジェクション攻撃への対策等を考慮する必要がある。<br> | <u>大きなファイルを扱う場合のメモリ使用量や外部からのXMLインジェクション攻撃への対策等を考慮する必要がある。</u><br> | ||
また、適切なエラーハンドリングや入力のサニタイズも重要である。<br> | <u>また、適切なエラーハンドリングや入力のサニタイズも重要である。</u><br> | ||
<br> | <br> | ||
C#におけるXMLファイルの扱いは、.NET Frameworkの進化とともに改善されており、より効率的で柔軟になってきている。<br> | C#におけるXMLファイルの扱いは、.NET Frameworkの進化とともに改善されており、より効率的で柔軟になってきている。<br> | ||
<br><br> | |||
== 要素の取得 == | |||
以下の例では、XMLファイルを読み込み、以下に示す要素を読み込んでいる。<br> | |||
* <Hypocenter> -> <Area> -> <Name>の値 | |||
* <Hypocenter> -> <Area> -> <nowiki><Code></nowiki>のtype属性の値 | |||
* 全ての<Observation> -> <IntensityStation> -> <Name>の値 | |||
<br> | |||
読み込むXMLファイルを以下に示す。<br> | |||
<syntaxhighlight lang="xml"> | |||
<!-- 使用するXMLファイル --> | |||
<Earthquake> | |||
<OriginTime>2024-08-23T21:00:00+09:00</OriginTime> | |||
<ArrivalTime>2024-08-23T21:01:00+09:00</ArrivalTime> | |||
<Hypocenter> | |||
<Area> | |||
<Name>茨城県南部</Name> | |||
<Code type="震央地名">301</Code> | |||
</Area> | |||
</Hypocenter> | |||
<jmx_eb:Magnitude type="Mj" description="M3.8">3.8</jmx_eb:Magnitude> | |||
</Earthquake> | |||
<Observation> | |||
<Pref><Name>茨城県</Name><Code>08</Code><MaxInt>2</MaxInt> | |||
<Area><Name>茨城県北部</Name><Code>300</Code><MaxInt>2</MaxInt> | |||
<City><Name>小美玉市</Name><Code>0823600</Code><MaxInt>2</MaxInt> | |||
<IntensityStation><Name>小美玉市小川*</Name><Code>0823633</Code><Int>2</Int></IntensityStation> | |||
<IntensityStation><Name>小美玉市上玉里*</Name><Code>0823635</Code><Int>2</Int></IntensityStation> | |||
</City> | |||
<City><Name>水戸市</Name><Code>0820100</Code><MaxInt>1</MaxInt> | |||
<IntensityStation><Name>水戸市千波町*</Name><Code>0820121</Code><Int>1</Int></IntensityStation> | |||
</City> | |||
</Area> | |||
</Pref> | |||
</Observation> | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
using System; | |||
using System.IO; | |||
using System.Collections.Generic; | |||
using System.Xml; | |||
using System.Threading.Tasks; | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
string xmlFilePath = "sample.xml"; // XMLファイルのパスを指定 | |||
try | |||
{ | |||
var (hypocenterAreaName, hypocenterAreaCodeType, intensityStationNames) = await ParseXmlFileAsync(xmlFilePath); | |||
// 結果を出力 | |||
Console.WriteLine($"震源地: {hypocenterAreaName}"); | |||
Console.WriteLine($"震央地名コードタイプ: {hypocenterAreaCodeType}"); | |||
Console.WriteLine("観測点:"); | |||
foreach (var name in intensityStationNames) | |||
{ | |||
Console.WriteLine($"- {name}"); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ | |||
Console.WriteLine($"エラーが発生: {ex.Message}"); | |||
} | |||
} | |||
// XMLファイルを非同期で解析 | |||
static async Task<(string hypocenterAreaName, string hypocenterAreaCodeType, List<string> intensityStationNames)> ParseXmlFileAsync(string filePath) | |||
{ | |||
string hypocenterAreaName = null; | |||
string hypocenterAreaCodeType = null; | |||
var intensityStationNames = new List<string>(); | |||
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous)) | |||
using (var reader = XmlReader.Create(stream, new XmlReaderSettings { Async = true })) | |||
{ | |||
while (await reader.ReadAsync()) | |||
{ | |||
if (reader.NodeType == XmlNodeType.Element) | |||
{ | |||
switch (reader.Name) | |||
{ | |||
case "Area": | |||
// Hypocenter内のAreaを処理 | |||
if (reader.Depth == 3 && hypocenterAreaName == null) | |||
{ | |||
(hypocenterAreaName, hypocenterAreaCodeType) = await ProcessHypocenterAreaAsync(reader); | |||
} | |||
break; | |||
case "IntensityStation": | |||
// IntensityStationを処理 | |||
await ProcessIntensityStationAsync(reader, intensityStationNames); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
return (hypocenterAreaName, hypocenterAreaCodeType, intensityStationNames); | |||
} | |||
// Hypocenter内のArea要素を非同期で処理 | |||
static async Task<(string areaName, string codeType)> ProcessHypocenterAreaAsync(XmlReader reader) | |||
{ | |||
string areaName = null; | |||
string codeType = null; | |||
await reader.ReadAsync(); // Area要素の子に移動 | |||
while (!(reader.NodeType == XmlNodeType.EndElement && reader.Name == "Area")) | |||
{ | |||
if (reader.NodeType == XmlNodeType.Element) | |||
{ | |||
switch (reader.Name) | |||
{ | |||
case "Name": | |||
areaName = await reader.ReadElementContentAsStringAsync(); | |||
break; | |||
case "Code": | |||
codeType = reader.GetAttribute("type"); | |||
await reader.SkipAsync(); // Code要素をスキップ | |||
break; | |||
} | |||
} | |||
else | |||
{ | |||
await reader.ReadAsync(); | |||
} | |||
} | |||
return (areaName, codeType); | |||
} | |||
// IntensityStation要素を非同期で処理 | |||
static async Task ProcessIntensityStationAsync(XmlReader reader, List<string> stationNames) | |||
{ | |||
await reader.ReadAsync(); // IntensityStation要素の子に移動 | |||
while (!(reader.NodeType == XmlNodeType.EndElement && reader.Name == "IntensityStation")) | |||
{ | |||
if (reader.NodeType == XmlNodeType.Element && reader.Name == "Name") | |||
{ | |||
stationNames.Add(await reader.ReadElementContentAsStringAsync()); | |||
} | |||
else | |||
{ | |||
await reader.ReadAsync(); | |||
} | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||