「C Sharpの基礎 - XML」の版間の差分
(→要素の取得) |
(→要素の取得) |
||
332行目: | 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> | </syntaxhighlight> | ||
<br><br> | <br><br> |
2024年9月18日 (水) 22:40時点における版
概要
XML (Extensible Markup Language) は、データを構造化して保存するためのフォーマットである。
C#では、System.Xml
名前空間を使用して、XMLファイルの読み書きや操作を行うことができる。
XMLファイルの基本的な構造は、ルート要素から始まり、その中に子要素やテキストノードが階層的に配置される。
各要素は開始タグと終了タグで囲まれ、属性を持つこともできる。
この構造により、データの意味や関係性を明確に表現することができる。
C#でXMLファイルを扱う場合によく使用されるクラスには、XmlReader
、XmlWriter
、XmlDocument
、XPath
等がある。
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>