「C Sharpの基礎 - XML」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
549行目: 549行目:
   </Pref>
   </Pref>
  </Observation>
  </Observation>
</syntaxhighlight>
<br><br>
== LINQ to XMLの使用 ==
==== 要素の取得 ====
以下の例では、非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。<br>
<br>
* <Hypocenter> -> <Area> -> <Name>の値
* <Hypocenter> -> <Area> -> <Code>のtype属性の値
* 全ての<Observation> -> <IntensityStation> -> <Name>の値
<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.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
    static async Task Main(string[] args)
    {
      try
      {
          // XMLファイルのパスを指定
          string xmlFilePath = "sample.xml";
          // XMLファイルを非同期で読み込み、XDocumentオブジェクトを生成
          XDocument doc = await Task.Run(() => XDocument.Load(xmlFilePath));
          // <Hypocenter> -> <Area> -> <Name>の値を取得
          string areaName = doc.Descendants("Hypocenter")
                              .Elements("Area")
                              .Elements("Name")
                              .FirstOrDefault()?.Value;
          Console.WriteLine($"震源地域名: {areaName}");
          // <Hypocenter> -> <Area> -> <Code>のtype属性の値を取得
          string codeType = doc.Descendants("Hypocenter")
                              .Elements("Area")
                              .Elements("Code")
                              .Attributes("type")
                              .FirstOrDefault()?.Value;
          Console.WriteLine($"コードタイプ: {codeType}");
          // 全ての<Observation> -> <IntensityStation> -> <Name>の値を取得
          var intensityStationNames = doc.Descendants("Observation")
                                        .Descendants("IntensityStation")
                                        .Elements("Name")
                                        .Select(e => e.Value)
                                        .ToList();
          Console.WriteLine("観測点名:");
          foreach (var name in intensityStationNames)
          {
            Console.WriteLine($"- {name}");
          }
          // ストリーミング処理を使用して大きなXMLファイルを効率的に処理する例
          await ProcessLargeXmlFileAsync(xmlFilePath);
      }
      catch (FileNotFoundException)
      {
          Console.WriteLine("エラー: 指定されたXMLファイルが存在しない");
      }
      catch (Exception ex)
      {
          Console.WriteLine($"エラー: XMLの処理中に問題が発生  詳細: {ex.Message}");
      }
    }
    // 大きなXMLファイルを効率的にストリーミング処理する
    static async Task ProcessLargeXmlFileAsync(string filePath)
    {
      Console.WriteLine("ストリーミング処理による大規模XMLファイルの処理:");
      using (var reader = new StreamReader(filePath))
      {
          using (var xmlReader = System.Xml.XmlReader.Create(reader))
          {
            while (await xmlReader.ReadAsync())
            {
                if (xmlReader.NodeType == System.Xml.XmlNodeType.Element)
                {
                  if (xmlReader.Name == "IntensityStation")
                  {
                      // IntensityStationの子要素を処理
                      var element  = await XElement.ReadFromAsync(xmlReader);
                      var name      = element.Element("Name")?.Value;
                      var code      = element.Element("Code")?.Value;
                      var intensity = element.Element("Int")?.Value;
                      Console.WriteLine($"観測点: {name}, コード: {code}, 震度: {intensity}");
                  }
                }
            }
          }
      }
    }
}
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>

2024年9月21日 (土) 00:20時点における版

概要

XML (Extensible Markup Language) は、データを構造化して保存するためのフォーマットである。
C#では、System.Xml名前空間を使用して、XMLファイルの読み書きや操作を行うことができる。

XMLファイルの基本的な構造は、ルート要素から始まり、その中に子要素やテキストノードが階層的に配置される。
各要素は開始タグと終了タグで囲まれ、属性を持つこともできる。
この構造により、データの意味や関係性を明確に表現することができる。

C#でXMLファイルを扱う場合によく使用されるクラスには、XmlReaderXmlWriterXmlDocumentXPath等がある。
XmlReaderクラスとXmlWriterクラスは高速で効率的なストリーミング処理を提供しており、大規模なXMLファイルの読み書きに適している。

一方、XmlDocumentクラスはXMLファイル全体をメモリ上に読み込み、ツリー構造として操作することができる。

XMLファイルの利用例としては、設定ファイル、データ交換、Webサービスの通信プロトコル (SOAP) 等が挙げられる。
特に、アプリケーションの設定情報をXMLファイルに保存することにより、プログラムの動作をコードを変更せずに柔軟に制御できるようになる。

また、LINQ to XMLを使用すると、XMLデータに対して強力なクエリや操作を行うことができる。
これにより、複雑なXML処理も直感的に記述することが可能になる。

※注意
大きなファイルを扱う場合のメモリ使用量や外部からのXMLインジェクション攻撃への対策等を考慮する必要がある。
また、適切なエラーハンドリングや入力のサニタイズも重要である。

C#におけるXMLファイルの扱いは、.NET Frameworkの進化とともに改善されており、より効率的で柔軟になってきている。


XMLファイルの作成

以下の例では、非同期処理とストリーミング処理を使用して、XmlWriterクラスで指定されたXML構造を持つ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>


 using System;
 using System.Xml;
 using System.Threading.Tasks;
 
 class Program
 {
    static async Task Main(string[] args)
    {
       string xmlFilePath = "sample.xml";
 
       try
       {
          await CreateEarthquakeXmlAsync(xmlFilePath);
       }
       catch (Exception ex)
       {
          Console.WriteLine($"エラーが発生: {ex.Message}");
       }
    }
 
    static async Task CreateEarthquakeXmlAsync(string filePath)
    {
       var settings = new XmlWriterSettings
       {
          Async = true,
          Indent = true
       };
 
       using (var writer = XmlWriter.Create(filePath, settings))
       {
          await writer.WriteStartDocumentAsync();
 
          // ルート要素は記述せずに直接コンテンツを記述する
          await WriteEarthquakeElementAsync(writer);
          await WriteObservationElementAsync(writer);
 
          await writer.WriteEndDocumentAsync();
       }
    }
 
    static async Task WriteEarthquakeElementAsync(XmlWriter writer)
    {
       await writer.WriteStartElementAsync(null, "Earthquake", null);
 
       await writer.WriteElementStringAsync(null, "OriginTime", null, "2024-08-23T21:00:00+09:00");
       await writer.WriteElementStringAsync(null, "ArrivalTime", null, "2024-08-23T21:01:00+09:00");
 
       await writer.WriteStartElementAsync(null, "Hypocenter", null);
       await writer.WriteStartElementAsync(null, "Area", null);
       await writer.WriteElementStringAsync(null, "Name", null, "茨城県南部");
         
       await writer.WriteStartElementAsync(null, "Code", null);
       await writer.WriteAttributeStringAsync(null, "type", null, "震央地名");
       await writer.WriteStringAsync("301");
       await writer.WriteEndElementAsync();
 
       await writer.WriteEndElementAsync();  // Area
       await writer.WriteEndElementAsync();  // Hypocenter
 
       await writer.WriteStartElementAsync("jmx_eb", "Magnitude", null);
       await writer.WriteAttributeStringAsync(null, "type", null, "Mj");
       await writer.WriteAttributeStringAsync(null, "description", null, "M3.8");
       await writer.WriteStringAsync("3.8");
       await writer.WriteEndElementAsync();
 
       await writer.WriteEndElementAsync();  // Earthquake
    }
 
    static async Task WriteObservationElementAsync(XmlWriter writer)
    {
       await writer.WriteStartElementAsync(null, "Observation", null);
 
       await writer.WriteStartElementAsync(null, "Pref", null);
       await writer.WriteElementStringAsync(null, "Name", null, "茨城県");
       await writer.WriteElementStringAsync(null, "Code", null, "08");
       await writer.WriteElementStringAsync(null, "MaxInt", null, "2");
 
       await writer.WriteStartElementAsync(null, "Area", null);
       await writer.WriteElementStringAsync(null, "Name", null, "茨城県北部");
       await writer.WriteElementStringAsync(null, "Code", null, "300");
       await writer.WriteElementStringAsync(null, "MaxInt", null, "2");
 
       // 小美玉市
       await writer.WriteStartElementAsync(null, "City", null);
       await writer.WriteElementStringAsync(null, "Name", null, "小美玉市");
       await writer.WriteElementStringAsync(null, "Code", null, "0823600");
       await writer.WriteElementStringAsync(null, "MaxInt", null, "2");
 
       await WriteIntensityStationAsync(writer, "小美玉市小川*", "0823633", "2");
       await WriteIntensityStationAsync(writer, "小美玉市上玉里*", "0823635", "2");
 
       await writer.WriteEndElementAsync();  // City
 
       // 水戸市
       await writer.WriteStartElementAsync(null, "City", null);
       await writer.WriteElementStringAsync(null, "Name", null, "水戸市");
       await writer.WriteElementStringAsync(null, "Code", null, "0820100");
       await writer.WriteElementStringAsync(null, "MaxInt", null, "1");
 
       await WriteIntensityStationAsync(writer, "水戸市千波町*", "0820121", "1");
 
       await writer.WriteEndElementAsync();  // City
 
       await writer.WriteEndElementAsync();  // Area
       await writer.WriteEndElementAsync();  // Pref
       await writer.WriteEndElementAsync();  // Observation
    }
 
    static async Task WriteIntensityStationAsync(XmlWriter writer, string name, string code, string intensity)
    {
       await writer.WriteStartElementAsync(null, "IntensityStation", null);
       await writer.WriteElementStringAsync(null, "Name", null, name);
       await writer.WriteElementStringAsync(null, "Code", null, code);
       await writer.WriteElementStringAsync(null, "Int", null, intensity);
       await writer.WriteEndElementAsync();
    }
 }



要素の取得

以下の例では、非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。

  • <Hypocenter> -> <Area> -> <Name>の値
  • <Hypocenter> -> <Area> -> <Code>のtype属性の値
  • 全ての<Observation> -> <IntensityStation> -> <Name>の値


読み込む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>


 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();
          }
       }
    }
 }



要素の変更

以下の例では、非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。

  • <Hypocenter> -> <Area> -> <Name>の値をhogeに変更
  • <Hypocenter> -> <Area> -> <Code>のtype属性の値を"99に変更
  • 全ての<Observation> -> <IntensityStation> -> <Name>の値をpiyoに変更


読み込む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>


 using System;
 using System.IO;
 using System.Xml;
 using System.Threading.Tasks;
 
 class Program
 {
    static async Task Main(string[] args)
    {
       string inputXmlPath = "input.xml";
       string outputXmlPath = "output.xml";
 
       try
       {
          await ModifyXmlFileAsync(inputXmlPath, outputXmlPath);
       }
       catch (Exception ex)
       {
          Console.WriteLine($"エラーが発生: {ex.Message}");
       }
    }
 
    static async Task ModifyXmlFileAsync(string inputPath, string outputPath)
    {
       var readerSettings = new XmlReaderSettings { Async = true };
       var writerSettings = new XmlWriterSettings { Async = true, Indent = true };
 
       using (var reader = XmlReader.Create(inputPath, readerSettings))
       using (var writer = XmlWriter.Create(outputPath, writerSettings))
       {
          await writer.WriteStartDocumentAsync();
 
          while (await reader.ReadAsync())
          {
             switch (reader.NodeType)
             {
                case XmlNodeType.Element:
                   await ProcessElementAsync(reader, writer);
                   break;
                case XmlNodeType.Text:
                   await writer.WriteStringAsync(reader.Value);
                   break;
                case XmlNodeType.XmlDeclaration:
                case XmlNodeType.ProcessingInstruction:
                   await writer.WriteProcessingInstructionAsync(reader.Name, reader.Value);
                   break;
                case XmlNodeType.Comment:
                   await writer.WriteCommentAsync(reader.Value);
                   break;
                case XmlNodeType.EndElement:
                   await writer.WriteEndElementAsync();
                   break;
                default:
                   await writer.WriteNodeAsync(reader, false);
                   break;
             }
          }
 
          await writer.WriteEndDocumentAsync();
       }
    }
 
    static async Task ProcessElementAsync(XmlReader reader, XmlWriter writer)
    {
       if (reader.Name == "Area" && reader.Depth == 3) // Hypocenter -> Area
       {
          await writer.WriteStartElementAsync(reader.Prefix, reader.LocalName, reader.NamespaceURI);
          await ModifyHypocenterAreaAsync(reader, writer);
       }
       else if (reader.Name == "IntensityStation")
       {
          await writer.WriteStartElementAsync(reader.Prefix, reader.LocalName, reader.NamespaceURI);
          await ModifyIntensityStationAsync(reader, writer);
       }
       else
       {
          await writer.WriteStartElementAsync(reader.Prefix, reader.LocalName, reader.NamespaceURI);
          if (reader.HasAttributes)
          {
             await WriteAttributesAsync(reader, writer);
          }
       }
    }
 
    static async Task ModifyHypocenterAreaAsync(XmlReader reader, XmlWriter writer)
    {
       while (await reader.ReadAsync())
       {
          if (reader.NodeType == XmlNodeType.Element)
          {
             if (reader.Name == "Name")
             {
                await writer.WriteElementStringAsync(reader.Prefix, "Name", reader.NamespaceURI, "hoge");
                await reader.ReadAsync(); // Skip the original content
             }
             else if (reader.Name == "Code")
             {
                await writer.WriteStartElementAsync(reader.Prefix, "Code", reader.NamespaceURI);
                await writer.WriteAttributeStringAsync(null, "type", null, "99");
                await writer.WriteStringAsync(await reader.ReadElementContentAsStringAsync());
                await writer.WriteEndElementAsync();
             }
             else
             {
                await writer.WriteNodeAsync(reader, false);
             }
          }
          else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "Area")
          {
             break;
          }
       }
    }
 
    static async Task ModifyIntensityStationAsync(XmlReader reader, XmlWriter writer)
    {
       while (await reader.ReadAsync())
       {
          if (reader.NodeType == XmlNodeType.Element)
          {
             if (reader.Name == "Name")
             {
                await writer.WriteElementStringAsync(reader.Prefix, "Name", reader.NamespaceURI, "piyo");
                await reader.ReadAsync(); // Skip the original content
             }
             else
             {
                await writer.WriteNodeAsync(reader, false);
             }
          }
          else if (reader.NodeType == XmlNodeType.EndElement && reader.Name == "IntensityStation")
          {
             break;
          }
       }
    }
 
    static async Task WriteAttributesAsync(XmlReader reader, XmlWriter writer)
    {
       for (int i = 0; i < reader.AttributeCount; i++)
       {
          reader.MoveToAttribute(i);
          await writer.WriteAttributeStringAsync(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.Value);
       }
       reader.MoveToElement();
    }
 }


 <!-- 変更後のXMLファイル -->
 
 <?xml version="1.0" encoding="utf-8"?>
 <Earthquake>
   <OriginTime>2024-08-23T21:00:00+09:00</OriginTime>
   <ArrivalTime>2024-08-23T21:01:00+09:00</ArrivalTime>
   <Hypocenter>
     <Area>
       <Name>hoge</Name>
       <Code type="99">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>piyo</Name><Code>0823633</Code><Int>2</Int></IntensityStation>
         <IntensityStation><Name>piyo</Name><Code>0823635</Code><Int>2</Int></IntensityStation>
       </City>
       <City><Name>水戸市</Name><Code>0820100</Code><MaxInt>1</MaxInt>
         <IntensityStation><Name>piyo</Name><Code>0820121</Code><Int>1</Int></IntensityStation>
       </City>
     </Area>
   </Pref>
 </Observation>



LINQ to XMLの使用

要素の取得

以下の例では、非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。

  • <Hypocenter> -> <Area> -> <Name>の値
  • <Hypocenter> -> <Area> -> のtype属性の値
  • 全ての<Observation> -> <IntensityStation> -> <Name>の値


 <!-- 使用する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>


 using System;
 using System.IO;
 using System.Linq;
 using System.Xml.Linq;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 
 class Program
 {
    static async Task Main(string[] args)
    {
       try
       {
          // XMLファイルのパスを指定
          string xmlFilePath = "sample.xml";
 
          // XMLファイルを非同期で読み込み、XDocumentオブジェクトを生成
          XDocument doc = await Task.Run(() => XDocument.Load(xmlFilePath));
 
          // <Hypocenter> -> <Area> -> <Name>の値を取得
          string areaName = doc.Descendants("Hypocenter")
                               .Elements("Area")
                               .Elements("Name")
                               .FirstOrDefault()?.Value;
 
          Console.WriteLine($"震源地域名: {areaName}");
 
          // <Hypocenter> -> <Area> -> <Code>のtype属性の値を取得
          string codeType = doc.Descendants("Hypocenter")
                               .Elements("Area")
                               .Elements("Code")
                               .Attributes("type")
                               .FirstOrDefault()?.Value;
 
          Console.WriteLine($"コードタイプ: {codeType}");
 
          // 全ての<Observation> -> <IntensityStation> -> <Name>の値を取得
          var intensityStationNames = doc.Descendants("Observation")
                                         .Descendants("IntensityStation")
                                         .Elements("Name")
                                         .Select(e => e.Value)
                                         .ToList();
 
          Console.WriteLine("観測点名:");
          foreach (var name in intensityStationNames)
          {
             Console.WriteLine($"- {name}");
          }
 
          // ストリーミング処理を使用して大きなXMLファイルを効率的に処理する例
          await ProcessLargeXmlFileAsync(xmlFilePath);
       }
       catch (FileNotFoundException)
       {
          Console.WriteLine("エラー: 指定されたXMLファイルが存在しない");
       }
       catch (Exception ex)
       {
          Console.WriteLine($"エラー: XMLの処理中に問題が発生  詳細: {ex.Message}");
       }
    }
 
    // 大きなXMLファイルを効率的にストリーミング処理する
    static async Task ProcessLargeXmlFileAsync(string filePath)
    {
       Console.WriteLine("ストリーミング処理による大規模XMLファイルの処理:");
 
       using (var reader = new StreamReader(filePath))
       {
          using (var xmlReader = System.Xml.XmlReader.Create(reader))
          {
             while (await xmlReader.ReadAsync())
             {
                if (xmlReader.NodeType == System.Xml.XmlNodeType.Element)
                {
                   if (xmlReader.Name == "IntensityStation")
                   {
                      // IntensityStationの子要素を処理
                      var element   = await XElement.ReadFromAsync(xmlReader);
                      var name      = element.Element("Name")?.Value;
                      var code      = element.Element("Code")?.Value;
                      var intensity = element.Element("Int")?.Value;
 
                      Console.WriteLine($"観測点: {name}, コード: {code}, 震度: {intensity}");
                   }
                }
             }
          }
       }
    }
 }