📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の7版が非表示) | |||
| 23行目: | 23行目: | ||
<br> | <br> | ||
C#におけるXMLファイルの扱いは、.NET Frameworkの進化とともに改善されており、より効率的で柔軟になってきている。<br> | C#におけるXMLファイルの扱いは、.NET Frameworkの進化とともに改善されており、より効率的で柔軟になってきている。<br> | ||
<br><br> | |||
== XMLファイルの作成 == | |||
以下の例では、非同期処理とストリーミング処理を使用して、XmlWriterクラスで指定されたXML構造を持つXMLファイルを生成している。<br> | |||
<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.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(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
== 要素の取得 == | == 要素の取得 == | ||
以下の例では、非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。<br> | |||
* <Hypocenter> -> <Area> -> <Name>の値 | * <Hypocenter> -> <Area> -> <Name>の値 | ||
* <Hypocenter> -> <Area> -> <nowiki><Code></nowiki>のtype属性の値 | * <Hypocenter> -> <Area> -> <nowiki><Code></nowiki>のtype属性の値 | ||
| 179行目: | 332行目: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
<br><br> | |||
== 要素の変更 == | |||
以下の例では、非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。<br> | |||
* <Hypocenter> -> <Area> -> <Name>の値をhogeに変更 | |||
* <Hypocenter> -> <Area> -> <nowiki><Code></nowiki>のtype属性の値を"99に変更 | |||
* 全ての<Observation> -> <IntensityStation> -> <Name>の値をpiyoに変更 | |||
<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.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(); | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="xml"> | |||
<!-- 変更後の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> | |||
</syntaxhighlight> | |||
<br><br> | |||
== LINQ to XMLの使用 == | |||
==== XMLファイルの作成 ==== | |||
以下の例では、LINQ to XMLを使用して、下記のXMLファイルを非同期で生成している。<br> | |||
非同期処理およびストリーミング処理を使用しているため、大きなXMLファイルを扱う場合でもメモリ効率が良く、アプリケーションの応答性を維持している。<br> | |||
<br> | |||
* GenerateEarthquakeXmlAsyncメソッド | |||
*: LINQ to XMLを使用してXMLドキュメントを構築する。 | |||
*: 指定されたXML構造に従って、全ての要素と属性を作成する。 | |||
*: jmx_eb名前空間を使用して、特定の要素に名前空間を適用している。 | |||
* SaveXmlToFileAsyncメソッド | |||
*: ストリーミング処理を使用して、XMLドキュメントをファイルに非同期で保存する。 | |||
*: FileStreamクラスを使用して、非同期I/O操作を行う。 | |||
<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.Xml.Linq; | |||
using System.Threading.Tasks; | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
try | |||
{ | |||
// XMLドキュメントを生成 | |||
XDocument doc = await GenerateEarthquakeXmlAsync(); | |||
// ファイルに非同期で保存 | |||
await SaveXmlToFileAsync(doc, "sample.xml"); | |||
} | |||
catch (Exception ex) | |||
{ | |||
Console.WriteLine($"エラーが発生: {ex.Message}"); | |||
} | |||
} | |||
static async Task<XDocument> GenerateEarthquakeXmlAsync() | |||
{ | |||
// 非同期タスクをシミュレート | |||
await Task.Delay(100); | |||
// XMLの名前空間を定義 | |||
XNamespace jmx_eb = "http://www.jma.go.jp/jmx-eb"; | |||
// XMLドキュメントを作成 | |||
XDocument doc = new XDocument(new XElement("Root", | |||
new XElement("Earthquake", | |||
new XElement("OriginTime", "2024-08-23T21:00:00+09:00"), | |||
new XElement("ArrivalTime", "2024-08-23T21:01:00+09:00"), | |||
new XElement("Hypocenter", | |||
new XElement("Area", | |||
new XElement("Name", "茨城県南部"), | |||
new XElement("Code", new XAttribute("type", "震央地名"), "301") | |||
) | |||
), | |||
new XElement(jmx_eb + "Magnitude", | |||
new XAttribute("type", "Mj"), | |||
new XAttribute("description", "M3.8"), | |||
"3.8" | |||
) | |||
), | |||
new XElement("Observation", | |||
new XElement("Pref", | |||
new XElement("Name", "茨城県"), | |||
new XElement("Code", "08"), | |||
new XElement("MaxInt", "2"), | |||
new XElement("Area", | |||
new XElement("Name", "茨城県北部"), | |||
new XElement("Code", "300"), | |||
new XElement("MaxInt", "2"), | |||
new XElement("City", | |||
new XElement("Name", "小美玉市"), | |||
new XElement("Code", "0823600"), | |||
new XElement("MaxInt", "2"), | |||
new XElement("IntensityStation", | |||
new XElement("Name", "小美玉市小川*"), | |||
new XElement("Code", "0823633"), | |||
new XElement("Int", "2") | |||
), | |||
new XElement("IntensityStation", | |||
new XElement("Name", "小美玉市上玉里*"), | |||
new XElement("Code", "0823635"), | |||
new XElement("Int", "2") | |||
) | |||
), | |||
new XElement("City", | |||
new XElement("Name", "水戸市"), | |||
new XElement("Code", "0820100"), | |||
new XElement("MaxInt", "1"), | |||
new XElement("IntensityStation", | |||
new XElement("Name", "水戸市千波町*"), | |||
new XElement("Code", "0820121"), | |||
new XElement("Int", "1") | |||
) | |||
) | |||
) | |||
) | |||
) | |||
) | |||
); | |||
return doc; | |||
} | |||
static async Task SaveXmlToFileAsync(XDocument doc, string fileName) | |||
{ | |||
// ストリーミング処理を使用してファイルに非同期で保存 | |||
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) | |||
{ | |||
await doc.SaveAsync(fs, SaveOptions.None, default); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
==== 要素の取得 ==== | |||
以下の例では、LINQ to XMLおよび非同期処理を使用してXMLファイルを読み込み、以下に示す要素を読み込んでいる。<br> | |||
また、大きなXMLファイルを効率的に処理するためのストリーミング処理も実装している。<br> | |||
<br> | |||
<u>LINQ to XMLを使用する場合は、System.Xml.Linq名前空間を追加する必要がある。</u><br> | |||
<br> | |||
* <Hypocenter> -> <Area> -> <Name>の値 | |||
* <Hypocenter> -> <Area> -> <nowiki><Code></nowiki>のtype属性の値 | |||
* 全ての<Observation> -> <IntensityStation> -> <Name>の値 | |||
<br> | |||
* LINQ to XML | |||
*: XDocumentクラスとDescendantsメソッド、Elementsメソッド、Attributesメソッドを使用して、XMLデータを効率的にクエリする。 | |||
* ストリーミング処理 | |||
*: ProcessLargeXmlFileAsyncメソッドでは、XmlReaderクラスを使用して大きなXMLファイルを効率的に処理する。 | |||
*: これにより、メモリ使用量を抑えつつ、大規模な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.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> | |||
<br> | |||
==== 要素の変更 ==== | |||
以下の例では、LINQ to XMLを使用して、以下に示すXMLファイルの一部の値を変更している。<br> | |||
<br> | |||
* ModifyXmlFileAsync メソッド: | |||
*: FileStreamクラスを使用して、XMLファイルを非同期で読み込む。 | |||
*: LINQ to XMLを使用して、指定された要素と属性を検索して、値を変更する。 | |||
*: 変更後のXMLドキュメントを非同期で保存する。 | |||
*: <br> | |||
* 変更操作 | |||
*: <Hypocenter> -> <Area> -> <Name>の値を"hoge"に変更する。 | |||
*: <Hypocenter> -> <Area> -> <nowiki><Code></nowiki>のtype属性の値を"99"に変更する。 | |||
*: 全ての<Observation> -> <IntensityStation> -> <Name>の値を"piyo"に変更する。 | |||
*: <br> | |||
* 名前空間の処理 | |||
*: XMLドキュメントのデフォルト名前空間を取得して、要素の検索に使用する。 | |||
* 非同期処理 | |||
*: ファイルの読み込みと保存に非同期メソッドを使用する。 | |||
* ストリーミング処理 | |||
*: FileStreamクラスを使用して、ファイルの読み込みと保存をストリーミング方式で行う。 | |||
<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.Threading.Tasks; | |||
class Program | |||
{ | |||
static async Task Main(string[] args) | |||
{ | |||
try | |||
{ | |||
// XMLファイルのパス | |||
string filePath = "sample.xml"; | |||
// XMLファイルを非同期で読み込み、修正し、保存する | |||
await ModifyXmlFileAsync(filePath); | |||
} | |||
catch (Exception ex) | |||
{ | |||
Console.WriteLine($"エラーが発生: {ex.Message}"); | |||
} | |||
} | |||
static async Task ModifyXmlFileAsync(string filePath) | |||
{ | |||
// XMLファイルを非同期で読み込む | |||
XDocument doc; | |||
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)) | |||
{ | |||
doc = await XDocument.LoadAsync(fs, LoadOptions.None, default); | |||
} | |||
// XMLの名前空間を取得 | |||
XNamespace ns = doc.Root.GetDefaultNamespace(); | |||
// <Hypocenter> -> <Area> -> <Name>の値を変更 | |||
var hypocenterAreaName = doc.Descendants(ns + "Hypocenter") | |||
.Elements(ns + "Area") | |||
.Elements(ns + "Name") | |||
.FirstOrDefault(); | |||
if (hypocenterAreaName != null) | |||
{ | |||
hypocenterAreaName.Value = "hoge"; | |||
} | |||
// <Hypocenter> -> <Area> -> <Code>のtype属性の値を変更 | |||
var hypocenterAreaCode = doc.Descendants(ns + "Hypocenter") | |||
.Elements(ns + "Area") | |||
.Elements(ns + "Code") | |||
.FirstOrDefault(); | |||
if (hypocenterAreaCode != null) | |||
{ | |||
hypocenterAreaCode.Attribute("type").Value = "99"; | |||
} | |||
// 全ての<Observation> -> <IntensityStation> -> <Name>の値を変更 | |||
var intensityStationNames = doc.Descendants(ns + "Observation") | |||
.Descendants(ns + "IntensityStation") | |||
.Elements(ns + "Name"); | |||
foreach (var name in intensityStationNames) | |||
{ | |||
name.Value = "piyo"; | |||
} | |||
// 変更したXMLを非同期で保存 | |||
using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 4096, true)) | |||
{ | |||
await doc.SaveAsync(fs, SaveOptions.None, default); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<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>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> | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<br><br> | <br><br> | ||