C#でXMLを読み書き・解析する方法|XmlDocumentとLINQ to XMLの使い方を初心者向けに解説

はじめに

C#でXMLを扱う方法を理解しておくと、設定ファイルの読み込み、外部システムとのデータ連携、アプリケーション内の構造化データ管理など、さまざまな場面で役立ちます。

XMLは古くから使われているデータ形式ですが、現在でも業務システム、設定ファイル、API連携、帳票データなどで利用されることがあります。C#にはXMLを読み込み・解析・作成・更新するための機能が標準で用意されており、代表的な方法として「XmlDocument」と「LINQ to XML」があります。

この記事では、C#でXMLを読み書きする基本から、XmlDocumentとLINQ to XMLの違い、要素や属性の取得、XMLファイルの作成・更新・削除、実践的な使い方まで初心者向けに解説します。

1. C#でXMLを扱う前に知っておきたい基礎

1-1. XMLとは何か|C#でXMLを使う場面

XMLとは「Extensible Markup Language」の略で、データをタグで囲んで表現するマークアップ言語です。HTMLに似た見た目をしていますが、HTMLがWebページの表示を目的としているのに対し、XMLはデータの構造を表すことを目的としています。

C#でXMLを使う場面には、次のようなものがあります。

C#
// 例:アプリケーション設定をXMLから読み込む
// 例:外部サービスから受け取ったXMLレスポンスを解析する
// 例:商品一覧やユーザー情報をXMLファイルとして保存する
// 例:古い業務システムとのデータ連携にXMLを使う

現在はJSONが使われることも多いですが、XMLは階層構造や属性を持つデータを表現しやすく、既存システムでは今でもよく使われています。

1-2. XMLファイルの基本構造|要素・属性・テキスト・階層

XMLは、要素、属性、テキスト、階層構造で構成されます。たとえば、次のようなXMLを考えてみましょう。

XML
<?xml version="1.0" encoding="utf-8"?>
<books>
<book id="1">
<title>C#入門</title>
<price>3000</price>
</book>
<book id="2">
<title>XML基礎</title>
<price>2500</price>
</book>
</books>

このXMLでは、books がルート要素、book が子要素です。id="1" は属性、C#入門3000 はテキストです。

C#でXMLを解析するときは、「どの要素を取得するのか」「属性を読むのか」「テキストを読むのか」を意識することが大切です。

1-3. C#でXMLを読み書きする主な方法

C#でXMLを扱う主な方法には、次のようなものがあります。

C#
// XmlDocument
// DOM形式でXML全体を読み込み、ノードを操作する方法

// LINQ to XML
// XDocumentやXElementを使い、LINQで直感的にXMLを操作する方法

// XmlReader
// XMLを前から順番に読み込む高速な方法

// XmlWriter
// XMLを前から順番に書き込む方法

// XmlSerializer
// XMLとC#のオブジェクトを相互変換する方法

初心者がC# XML処理を学ぶ場合は、まず XmlDocumentLINQ to XML を理解するとよいでしょう。この2つを押さえれば、一般的なXMLの読み込み、解析、作成、更新は十分対応できます。

1-4. XmlDocumentとLINQ to XMLの違い

XmlDocument は、XMLをDOMツリーとして扱う従来からある方法です。XmlNodeXmlElement を使って、要素や属性を操作します。

一方、LINQ to XMLは、XDocumentXElement を使ってXMLを扱う比較的新しい書き方です。LINQの構文を使えるため、条件検索や一覧取得を簡潔に書けます。

たとえば、特定の book 要素を取得する場合、LINQ to XMLでは次のように書けます。

C#
var books = doc.Descendants("book")
.Where(x => (int)x.Element("price") >= 3000);

XmlDocumentではXPathを使って検索することが多く、次のように書きます。

C#
XmlNodeList nodes = doc.SelectNodes("//book[price >= 3000]");

どちらもXMLを扱えますが、書き方や得意な場面が異なります。

1-5. 初心者はどちらを使うべきか

これからC#でXML処理を学ぶ初心者には、基本的にはLINQ to XMLがおすすめです。理由は、コードが読みやすく、要素の取得や条件検索を直感的に書けるからです。

ただし、既存のプロジェクトで XmlDocument が使われている場合や、XPathを活用したい場合は、XmlDocumentを使う場面もあります。

新規開発ではLINQ to XML、既存コードの保守やXPath中心の処理ではXmlDocument、と考えると選びやすいです。

2. C#でXMLを読み込む方法

2-1. サンプルXMLファイルを用意する

まずは、次のような books.xml を用意します。

XML
<?xml version="1.0" encoding="utf-8"?>
<books>
<book id="1" category="programming">
<title>C#入門</title>
<author>山田太郎</author>
<price>3000</price>
</book>
<book id="2" category="database">
<title>SQL基礎</title>
<author>佐藤花子</author>
<price>2500</price>
</book>
</books>

このXMLファイルをC#から読み込み、要素や属性の値を取得していきます。

2-2. XmlDocumentでXMLファイルを読み込む

XmlDocument を使ってXMLファイルを読み込むには、Load メソッドを使います。

C#
using System;
using System.Xml;

class Program
{
static void Main()
{
XmlDocument doc = new XmlDocument();
doc.Load("books.xml");

XmlNode root = doc.DocumentElement;

Console.WriteLine(root.Name);
}
}

doc.Load("books.xml") でXMLファイル全体を読み込みます。DocumentElement はルート要素を表し、この例では books 要素が取得されます。

2-3. LINQ to XMLでXMLファイルを読み込む

LINQ to XMLでは、XDocument.Load を使います。

C#
using System;
using System.Xml.Linq;

class Program
{
static void Main()
{
XDocument doc = XDocument.Load("books.xml");

Console.WriteLine(doc.Root.Name);
}
}

doc.Root でルート要素を取得できます。LINQ to XMLはコードが短く、XMLの構造をC#のコードとして自然に扱いやすいのが特徴です。

2-4. 文字列のXMLを読み込む方法

ファイルではなく、文字列としてXMLを持っている場合もあります。その場合は、XmlDocumentでは LoadXml、LINQ to XMLでは Parse を使います。

C#
using System;
using System.Xml;

class Program
{
static void Main()
{
string xml = "<user><name>田中</name><age>30</age></user>";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

Console.WriteLine(doc.DocumentElement["name"].InnerText);
}
}

LINQ to XMLでは次のように書けます。

C#
using System;
using System.Xml.Linq;

class Program
{
static void Main()
{
string xml = "<user><name>田中</name><age>30</age></user>";

XElement element = XElement.Parse(xml);

Console.WriteLine(element.Element("name").Value);
}
}

文字列のXMLを扱う場合でも、ファイル読み込みと基本的な考え方は同じです。

2-5. XML読み込み時によくあるエラーと原因

XML読み込み時によくあるエラーには、次のようなものがあります。

C#
// ファイルが存在しない
// XMLのタグが閉じられていない
// ルート要素が複数ある
// 文字コードが合っていない
// アクセス権限がない
// パスの指定が間違っている

たとえば、次のXMLは正しくありません。

XML
<books>
<book>
<title>C#入門</title>
</books>

book 要素の終了タグがないため、読み込み時に例外が発生します。XMLは開始タグと終了タグの対応が厳密なので、形式が正しいか確認することが重要です。

3. XmlDocumentを使ってXMLを解析する方法

3-1. XmlDocumentの基本的な使い方

XmlDocument では、XML全体をツリー構造として読み込み、ノードをたどりながら値を取得します。

C#
XmlDocument doc = new XmlDocument();
doc.Load("books.xml");

XmlElement root = doc.DocumentElement;
Console.WriteLine(root.Name);

XmlDocument では、XMLの各部分を XmlNodeXmlElement として扱います。ルート要素、子要素、属性、テキストを順番に取得しながら処理していきます。

3-2. 特定の要素を取得する

特定の要素を取得するには、GetElementsByTagName を使えます。

C#
XmlNodeList titles = doc.GetElementsByTagName("title");

foreach (XmlNode title in titles)
{
Console.WriteLine(title.InnerText);
}

このコードでは、XML内のすべての title 要素を取得し、そのテキストを表示しています。

最初の1件だけ取得したい場合は、次のように書けます。

C#
XmlNode title = doc.GetElementsByTagName("title")[0];
Console.WriteLine(title.InnerText);

ただし、要素が存在しない場合はエラーになる可能性があるため、実際のコードではnullチェックや件数チェックを行うことが大切です。

3-3. 属性の値を取得する

属性の値を取得するには、Attributes を使います。

C#
XmlNode book = doc.GetElementsByTagName("book")[0];

string id = book.Attributes["id"].Value;
string category = book.Attributes["category"].Value;

Console.WriteLine(id);
Console.WriteLine(category);

book 要素の id 属性と category 属性を取得しています。

属性が存在しない可能性がある場合は、次のように安全に取得します。

C#
XmlAttribute attr = book.Attributes["id"];

if (attr != null)
{
Console.WriteLine(attr.Value);
}

XMLでは属性が省略されることもあるため、存在チェックを習慣にしておくと安全です。

3-4. 子要素・親要素をたどる

XmlDocument では、ChildNodesParentNodeFirstChild などを使ってノードの関係をたどれます。

C#
XmlNode book = doc.GetElementsByTagName("book")[0];

foreach (XmlNode child in book.ChildNodes)
{
Console.WriteLine($"{child.Name}: {child.InnerText}");
}

親要素を取得する場合は、ParentNode を使います。

C#
XmlNode title = doc.GetElementsByTagName("title")[0];
XmlNode parent = title.ParentNode;

Console.WriteLine(parent.Name);

この例では、title 要素の親である book 要素を取得できます。

3-5. XPathで目的のノードを検索する

XmlDocumentではXPathを使うと、目的のノードを柔軟に検索できます。

C#
XmlNode node = doc.SelectSingleNode("//book[@id='1']/title");

if (node != null)
{
Console.WriteLine(node.InnerText);
}

このコードでは、id 属性が 1book 要素の中にある title 要素を取得しています。

複数の要素を取得する場合は、SelectNodes を使います。

C#
XmlNodeList nodes = doc.SelectNodes("//book[@category='programming']");

foreach (XmlNode node in nodes)
{
Console.WriteLine(node["title"].InnerText);
}

XPathを使うと、階層が深いXMLでも目的のデータを効率よく取得できます。

3-6. XmlNodeとXmlElementの違い

XmlNode は、XML内のさまざまなノードを表す基本クラスです。要素、属性、テキスト、コメントなど、XMLを構成する多くのものをノードとして扱います。

一方、XmlElement は要素ノードを表します。つまり、<book><title> のようなタグ付きの要素を扱うときに使います。

C#
XmlNode node = doc.SelectSingleNode("//book");
XmlElement element = node as XmlElement;

if (element != null)
{
Console.WriteLine(element.GetAttribute("id"));
}

要素として属性を操作したい場合は、XmlElement に変換すると扱いやすくなります。

3-7. XmlDocumentを使うメリット・デメリット

XmlDocumentのメリットは、古くから使われているため情報が多く、既存のC#プロジェクトでもよく見かけることです。また、XPathとの相性がよく、複雑な条件でノードを検索できます。

一方で、コードがやや冗長になりやすく、LINQ to XMLに比べると読み書きしにくいと感じる場面があります。また、XML全体をメモリに読み込むため、非常に大きなXMLファイルを扱う場合は注意が必要です。

4. LINQ to XMLを使ってXMLを解析する方法

4-1. LINQ to XMLとは

LINQ to XMLは、C#でXMLを簡潔に扱うための機能です。XDocumentXElementXAttribute などのクラスを使い、LINQの構文でXMLを検索・抽出できます。

特に、要素の一覧を取得したり、条件に合うデータだけを抽出したりする処理が書きやすいです。

C#
var books = doc.Descendants("book")
.Where(x => (string)x.Attribute("category") == "programming");

このように、C#のコレクションを扱う感覚でXMLを処理できます。

4-2. XDocumentでXMLを読み込む

XMLファイル全体を読み込むには、XDocument.Load を使います。

C#
using System;
using System.Xml.Linq;

class Program
{
static void Main()
{
XDocument doc = XDocument.Load("books.xml");

Console.WriteLine(doc.Root.Name);
}
}

XDocument はXML文書全体を表します。ルート要素だけを扱いたい場合は、doc.Root を使います。

4-3. XElementで要素を取得する

特定の要素を取得するには、ElementElementsDescendants を使います。

C#
XElement root = doc.Root;

foreach (XElement book in root.Elements("book"))
{
string title = book.Element("title").Value;
Console.WriteLine(title);
}

Elements("book") は、直下の book 要素を取得します。階層を問わずすべての book 要素を取得したい場合は、Descendants("book") を使います。

C#
var books = doc.Descendants("book");

foreach (var book in books)
{
Console.WriteLine(book.Element("title").Value);
}

4-4. 属性の値を取得する

LINQ to XMLで属性を取得するには、Attribute メソッドを使います。

C#
foreach (XElement book in doc.Descendants("book"))
{
string id = book.Attribute("id").Value;
string category = book.Attribute("category").Value;

Console.WriteLine($"{id}: {category}");
}

属性が存在しない可能性がある場合は、キャストを使うと安全です。

C#
string id = (string)book.Attribute("id");

この書き方では、属性が存在しない場合に null が返ります。Value を直接使うとnull参照エラーになる可能性があるため、実務ではキャストを使う書き方が便利です。

4-5. LINQで条件に合う要素を検索する

LINQ to XMLの大きな特徴は、LINQで条件検索ができることです。

C#
var expensiveBooks = doc.Descendants("book")
.Where(book => (int)book.Element("price") >= 3000);

foreach (var book in expensiveBooks)
{
Console.WriteLine(book.Element("title").Value);
}

このコードでは、price が3000以上の本だけを抽出しています。

属性を条件にする場合は、次のように書けます。

C#
var programmingBooks = doc.Descendants("book")
.Where(book => (string)book.Attribute("category") == "programming");

foreach (var book in programmingBooks)
{
Console.WriteLine(book.Element("title").Value);
}

XMLから条件に合うデータを抽出したい場合、LINQ to XMLは非常に便利です。

4-6. 複数の要素をループ処理する

複数の要素をループ処理する場合も、LINQ to XMLはシンプルに書けます。

C#
foreach (XElement book in doc.Descendants("book"))
{
string title = (string)book.Element("title");
string author = (string)book.Element("author");
int price = (int)book.Element("price");

Console.WriteLine($"{title} / {author} / {price}円");
}

キャストを使うことで、文字列や数値として値を取り出せます。ただし、数値変換に失敗する可能性がある場合は、int.TryParse を使うと安全です。

C#
string priceText = (string)book.Element("price");

if (int.TryParse(priceText, out int price))
{
Console.WriteLine(price);
}

4-7. LINQ to XMLを使うメリット・デメリット

LINQ to XMLのメリットは、コードが短く読みやすいことです。C#のLINQに慣れている人であれば、XMLの条件検索や一覧取得を自然に書けます。

また、XMLの新規作成も直感的に書けるため、読み込みだけでなく書き込みにも向いています。

一方で、XPathを多用する既存コードとの相性はXmlDocumentほどよくありません。また、XmlDocumentと同じくXML全体をメモリに読み込むため、大容量XMLでは XmlReader の利用も検討する必要があります。

5. C#でXMLを書き込む・新規作成する方法

5-1. XmlDocumentでXMLを新規作成する

XmlDocumentでXMLを新規作成する場合は、CreateElement を使って要素を作成し、AppendChild で追加します。

C#
XmlDocument doc = new XmlDocument();

XmlDeclaration declaration = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.AppendChild(declaration);

XmlElement root = doc.CreateElement("books");
doc.AppendChild(root);

このコードでは、XML宣言とルート要素 books を作成しています。

5-2. XmlDocumentで要素と属性を追加する

要素や属性を追加するには、次のように書きます。

C#
XmlElement book = doc.CreateElement("book");
book.SetAttribute("id", "1");

XmlElement title = doc.CreateElement("title");
title.InnerText = "C#入門";

XmlElement price = doc.CreateElement("price");
price.InnerText = "3000";

book.AppendChild(title);
book.AppendChild(price);
root.AppendChild(book);

最終的には、次のようなXMLになります。

XML
<?xml version="1.0" encoding="utf-8"?>
<books>
<book id="1">
<title>C#入門</title>
<price>3000</price>
</book>
</books>

5-3. LINQ to XMLでXMLを新規作成する

LINQ to XMLでは、XMLの構造をそのままC#のコードで表現できます。

C#
XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement("books",
new XElement("book",
new XAttribute("id", "1"),
new XElement("title", "C#入門"),
new XElement("price", 3000)
)
)
);

XmlDocumentよりも階層構造が見た目で分かりやすく、XMLを新規作成する場合に便利です。

5-4. XElementで要素と属性を追加する

既存の XElement に新しい要素を追加するには、Add メソッドを使います。

C#
XElement root = new XElement("books");

root.Add(
new XElement("book",
new XAttribute("id", "1"),
new XElement("title", "C#入門"),
new XElement("price", 3000)
)
);

さらに別の本を追加する場合も、同じように Add を使います。

C#
root.Add(
new XElement("book",
new XAttribute("id", "2"),
new XElement("title", "XML基礎"),
new XElement("price", 2500)
)
);

LINQ to XMLは、C#でXMLを組み立てる処理をかなり直感的に書けます。

5-5. 作成したXMLをファイルに保存する

XmlDocumentで作成したXMLは、Save メソッドで保存できます。

C#
doc.Save("books.xml");

LINQ to XMLでも同じように Save メソッドを使います。

C#
doc.Save("books.xml");

ファイルパスを相対パスで指定した場合、実行ファイルの場所を基準に保存されることがあります。保存先が分からない場合は、絶対パスを指定すると確認しやすいです。

C#
doc.Save(@"C:\temp\books.xml");

5-6. インデント付きで見やすく保存する方法

LINQ to XMLの Save は、通常はインデント付きで保存されます。より細かく制御したい場合は、XmlWriterSettings を使います。

C#
using System.Xml;

XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
Encoding = System.Text.Encoding.UTF8
};

using (XmlWriter writer = XmlWriter.Create("books.xml", settings))
{
doc.Save(writer);
}

XmlDocumentでも同じように XmlWriter を使って保存できます。

C#
XmlWriterSettings settings = new XmlWriterSettings
{
Indent = true,
Encoding = System.Text.Encoding.UTF8
};

using (XmlWriter writer = XmlWriter.Create("books.xml", settings))
{
doc.Save(writer);
}

インデント付きで保存すると、人間が見ても読みやすいXMLになります。

6. C#でXMLを編集・更新・削除する方法

6-1. 既存の要素の値を変更する

XmlDocumentで要素の値を変更するには、対象ノードを取得して InnerText を変更します。

C#
XmlNode title = doc.SelectSingleNode("//book[@id='1']/title");

if (title != null)
{
title.InnerText = "C# XML入門";
}

LINQ to XMLでは、Value を変更します。

C#
XElement title = doc.Descendants("book")
.FirstOrDefault(x => (string)x.Attribute("id") == "1")
?.Element("title");

if (title != null)
{
title.Value = "C# XML入門";
}

6-2. 属性の値を変更する

XmlDocumentで属性を変更するには、SetAttribute を使います。

C#
XmlElement book = doc.SelectSingleNode("//book[@id='1']") as XmlElement;

if (book != null)
{
book.SetAttribute("category", "csharp");
}

LINQ to XMLでは、SetAttributeValue を使います。

C#
XElement book = doc.Descendants("book")
.FirstOrDefault(x => (string)x.Attribute("id") == "1");

if (book != null)
{
book.SetAttributeValue("category", "csharp");
}

SetAttributeValue は、属性が存在しない場合は追加し、存在する場合は更新します。

6-3. 新しい要素を追加する

XmlDocumentで新しい要素を追加するには、CreateElementAppendChild を使います。

C#
XmlElement stock = doc.CreateElement("stock");
stock.InnerText = "10";

XmlNode book = doc.SelectSingleNode("//book[@id='1']");

if (book != null)
{
book.AppendChild(stock);
}

LINQ to XMLでは、Add を使います。

C#
XElement book = doc.Descendants("book")
.FirstOrDefault(x => (string)x.Attribute("id") == "1");

if (book != null)
{
book.Add(new XElement("stock", 10));
}

6-4. 不要な要素を削除する

XmlDocumentで要素を削除するには、親ノードから RemoveChild を呼び出します。

C#
XmlNode book = doc.SelectSingleNode("//book[@id='2']");

if (book != null && book.ParentNode != null)
{
book.ParentNode.RemoveChild(book);
}

LINQ to XMLでは、対象の XElement に対して Remove を呼び出します。

C#
XElement book = doc.Descendants("book")
.FirstOrDefault(x => (string)x.Attribute("id") == "2");

book?.Remove();

LINQ to XMLの方が削除処理はかなり簡潔に書けます。

6-5. XmlDocumentで更新するコード例

XmlDocumentでXMLを読み込み、値を更新して保存する一連のコードは次のとおりです。

C#
using System;
using System.Xml;

class Program
{
static void Main()
{
XmlDocument doc = new XmlDocument();
doc.Load("books.xml");

XmlNode title = doc.SelectSingleNode("//book[@id='1']/title");

if (title != null)
{
title.InnerText = "C# XML完全入門";
}

XmlElement book = doc.SelectSingleNode("//book[@id='1']") as XmlElement;

if (book != null)
{
book.SetAttribute("category", "csharp");
}

doc.Save("books.xml");

Console.WriteLine("XMLを更新しました。");
}
}

SelectSingleNode で対象を検索し、値や属性を変更してから Save で保存します。

6-6. LINQ to XMLで更新するコード例

LINQ to XMLで同じような更新処理を書くと、次のようになります。

C#
using System;
using System.Linq;
using System.Xml.Linq;

class Program
{
static void Main()
{
XDocument doc = XDocument.Load("books.xml");

XElement book = doc.Descendants("book")
.FirstOrDefault(x => (string)x.Attribute("id") == "1");

if (book != null)
{
book.Element("title")!.Value = "C# XML完全入門";
book.SetAttributeValue("category", "csharp");
}

doc.Save("books.xml");

Console.WriteLine("XMLを更新しました。");
}
}

LINQ to XMLでは、条件に合う要素を検索し、その要素に対して値や属性を更新します。C#のLINQに慣れている場合は、こちらの方が読みやすいでしょう。

7. XmlDocumentとLINQ to XMLの使い分け

7-1. XmlDocumentが向いているケース

XmlDocumentは、既存コードで使われている場合や、XPathを多用する場合に向いています。

C#
XmlNode node = doc.SelectSingleNode("//book[@id='1']/title");

XPathで複雑な検索条件を表現したい場合、XmlDocumentは便利です。また、古い.NET FrameworkのプロジェクトではXmlDocumentが使われていることも多いため、保守開発では理解しておく必要があります。

7-2. LINQ to XMLが向いているケース

LINQ to XMLは、新しくC#でXML処理を書く場合に向いています。コードが短く、条件検索や集計処理も書きやすいです。

C#
var books = doc.Descendants("book")
.Where(x => (int)x.Element("price") >= 3000)
.Select(x => new
{
Title = (string)x.Element("title"),
Price = (int)x.Element("price")
});

XMLから一覧データを取り出して処理する場合、LINQ to XMLは非常に扱いやすい方法です。

7-3. 既存コード・古い.NET環境での選び方

既存プロジェクトですでにXmlDocumentが使われている場合は、無理にLINQ to XMLへ置き換える必要はありません。既存コードとの統一感を優先した方が、保守しやすい場合があります。

一方、新規開発や学習目的であれば、LINQ to XMLから学ぶのがおすすめです。特に.NET 6、.NET 8などの比較的新しい環境では、LINQ to XMLを使うことで簡潔なコードを書きやすくなります。

7-4. 読みやすさ・書きやすさの比較

XmlDocumentは、ノードを1つずつ操作するため、処理の流れは分かりやすい反面、コードが長くなりがちです。

C#
XmlNode node = doc.SelectSingleNode("//book/title");

if (node != null)
{
Console.WriteLine(node.InnerText);
}

LINQ to XMLでは、同じ処理をより簡潔に書けます。

C#
var title = doc.Descendants("book")
.FirstOrDefault()
?.Element("title")?.Value;

読みやすさを重視するなら、LINQ to XMLの方が初心者にも扱いやすいでしょう。

7-5. パフォーマンス面での注意点

XmlDocumentもLINQ to XMLも、基本的にはXML全体をメモリに読み込んで処理します。そのため、数MB程度のXMLであれば問題になりにくいですが、数百MB以上の大きなXMLファイルではメモリ使用量に注意が必要です。

大きなXMLファイルを処理する場合は、XmlReader を使って必要な部分だけを順番に読み込む方法を検討します。

C#
using XmlReader reader = XmlReader.Create("large.xml");

while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "book")
{
Console.WriteLine("book要素を見つけました");
}
}

大容量データでは、XML全体を読み込まない設計が重要です。

7-6. 初心者におすすめの選び方

初心者がC# XML処理を学ぶなら、まずはLINQ to XMLをおすすめします。理由は、コードが短く、XMLの構造とC#のコードが対応しやすいからです。

ただし、業務ではXmlDocumentを使った既存コードに出会うこともあります。そのため、最初にLINQ to XMLで基本を学び、その後XmlDocumentとXPathも理解しておくと実践で困りにくくなります。

8. C#でXMLを扱うときの注意点

8-1. XMLファイルの文字コードに注意する

XMLファイルには、文字コードが指定されていることがあります。

XML
<?xml version="1.0" encoding="utf-8"?>

C#でXMLを読み込むとき、ファイルの実際の文字コードとXML宣言の encoding が一致していないと、文字化けや読み込みエラーの原因になります。

日本語を含むXMLでは、基本的にUTF-8で保存しておくと扱いやすいです。

8-2. null参照エラーを防ぐ書き方

XML処理でよくあるエラーが、存在しない要素や属性にアクセスして発生するnull参照エラーです。

たとえば、次のコードは title 要素が存在しない場合にエラーになる可能性があります。

C#
string title = book.Element("title").Value;

安全に書くなら、次のようにします。

C#
string title = (string)book.Element("title") ?? "";

XmlDocumentの場合も同様です。

C#
XmlNode node = doc.SelectSingleNode("//title");

if (node != null)
{
Console.WriteLine(node.InnerText);
}

XMLの構造が常に期待どおりとは限らないため、nullチェックを入れることが大切です。

8-3. 存在しない要素・属性への対処

存在しない要素や属性に対しては、初期値を設定する方法がよく使われます。

C#
string category = (string)book.Attribute("category") ?? "未分類";

数値の場合は、変換エラーにも注意します。

C#
int price = 0;
int.TryParse((string)book.Element("price"), out price);

外部から受け取るXMLでは、要素が不足していたり、値の形式が想定と違ったりすることがあります。安全に処理するためには、必ず存在チェックと変換チェックを行いましょう。

8-4. XMLの形式が正しくない場合の対処

XMLの形式が正しくない場合、読み込み時に例外が発生します。代表的なのは XmlException です。

C#
try
{
XDocument doc = XDocument.Load("books.xml");
}
catch (System.Xml.XmlException ex)
{
Console.WriteLine("XMLの形式が正しくありません。");
Console.WriteLine(ex.Message);
}

XMLはタグの閉じ忘れ、ルート要素の重複、不正な文字などに厳密です。読み込みに失敗した場合は、XMLファイルの内容を確認しましょう。

8-5. 外部XMLを読み込むときのセキュリティ注意点

外部から受け取ったXMLを読み込む場合は、セキュリティに注意が必要です。特に、外部実体参照やDTDを悪用した攻撃を防ぐため、XmlReaderSettings を使って安全に読み込むことを検討します。

C#
XmlReaderSettings settings = new XmlReaderSettings
{
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null
};

using XmlReader reader = XmlReader.Create("external.xml", settings);
XDocument doc = XDocument.Load(reader);

信頼できないXMLをそのまま読み込むのは危険です。外部XMLを扱う場合は、DTDの処理を禁止する、不要な外部参照を無効にするなどの対策を行いましょう。

8-6. 例外処理の書き方

XMLファイルの読み込みや保存では、ファイルが存在しない、アクセス権限がない、XML形式が不正など、さまざまな例外が発生する可能性があります。

C#
try
{
XDocument doc = XDocument.Load("books.xml");

// XML処理
}
catch (System.IO.FileNotFoundException)
{
Console.WriteLine("XMLファイルが見つかりません。");
}
catch (System.Xml.XmlException ex)
{
Console.WriteLine("XMLの形式が正しくありません。");
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("予期しないエラーが発生しました。");
Console.WriteLine(ex.Message);
}

実務では、エラー内容をログに出力し、ユーザーには分かりやすいメッセージを表示することが多いです。

9. よくあるC# XML処理の実践例

9-1. 設定ファイルとしてXMLを読み込む

XMLはアプリケーション設定ファイルとして使えます。

XML
<settings>
<database>
<host>localhost</host>
<port>5432</port>
</database>
</settings>

LINQ to XMLで読み込む例です。

C#
XDocument doc = XDocument.Load("settings.xml");

string host = (string)doc.Root.Element("database").Element("host");
int port = (int)doc.Root.Element("database").Element("port");

Console.WriteLine($"{host}:{port}");

設定値をXMLにまとめておくと、アプリケーションの動作をファイルで変更できるようになります。

9-2. XMLから一覧データを取得する

商品一覧や書籍一覧のようなデータをXMLから取得する場合、LINQ to XMLが便利です。

C#
var books = XDocument.Load("books.xml")
.Descendants("book")
.Select(book => new
{
Id = (string)book.Attribute("id"),
Title = (string)book.Element("title"),
Price = (int)book.Element("price")
});

foreach (var book in books)
{
Console.WriteLine($"{book.Id}: {book.Title} - {book.Price}円");
}

XMLの各要素をC#の匿名オブジェクトに変換することで、その後の処理がしやすくなります。

9-3. XMLの値を条件付きで抽出する

条件に合うデータだけを抽出する例です。

C#
XDocument doc = XDocument.Load("books.xml");

var result = doc.Descendants("book")
.Where(book => (int)book.Element("price") >= 3000)
.Select(book => (string)book.Element("title"));

foreach (var title in result)
{
Console.WriteLine(title);
}

このコードでは、価格が3000円以上の本のタイトルだけを取得しています。LINQを使うと、XMLの検索条件を分かりやすく書けます。

9-4. XMLにデータを追記して保存する

既存のXMLに新しいデータを追加して保存する例です。

C#
XDocument doc = XDocument.Load("books.xml");

doc.Root.Add(
new XElement("book",
new XAttribute("id", "3"),
new XAttribute("category", "network"),
new XElement("title", "ネットワーク入門"),
new XElement("author", "鈴木一郎"),
new XElement("price", 2800)
)
);

doc.Save("books.xml");

doc.Root.Add を使うことで、ルート要素の下に新しい book 要素を追加できます。

9-5. XMLをオブジェクトに変換する考え方

XMLを扱うときは、読み込んだ値をC#のクラスに変換すると管理しやすくなります。

C#
class Book
{
public string Id { get; set; } = "";
public string Title { get; set; } = "";
public int Price { get; set; }
}

XMLから Book オブジェクトの一覧に変換する例です。

C#
List<Book> books = doc.Descendants("book")
.Select(book => new Book
{
Id = (string)book.Attribute("id") ?? "",
Title = (string)book.Element("title") ?? "",
Price = (int?)book.Element("price") ?? 0
})
.ToList();

XMLのまま処理するより、C#のオブジェクトに変換した方が、その後の検索、表示、保存処理を行いやすくなります。

9-6. JSONとの使い分け

現在のWeb APIではJSONがよく使われますが、XMLにも強みがあります。

JSONは軽量で、JavaScriptやWeb APIとの相性がよい形式です。一方、XMLは属性や名前空間、スキーマ定義などを使えるため、複雑な文書構造や厳密なデータ定義に向いています。

C#で新しくデータ連携を作るならJSONが選ばれることも多いですが、既存システム、業務システム、設定ファイル、SOAP連携などではXMLが必要になる場面があります。

10. C#のXML処理でよくある質問

10-1. XmlDocumentとXDocumentは何が違う?

XmlDocumentは従来からあるDOMベースのXML操作方法で、XmlNodeXmlElement を使います。XPathで検索しやすく、既存コードでもよく使われます。

XDocumentはLINQ to XMLで使うクラスで、XElementXAttribute と組み合わせてXMLを扱います。LINQで条件検索しやすく、コードが簡潔になりやすいです。

初心者や新規開発では、XDocumentを使うLINQ to XMLがおすすめです。

10-2. XMLの属性と要素はどう使い分ける?

属性は、要素を補足する短い情報に向いています。

XML
<book id="1" category="programming">

要素は、データ本体や階層を持つ情報に向いています。

XML
<title>C#入門</title>
<price>3000</price>

IDや種別のような補足情報は属性、タイトルや価格のようなデータ本体は要素にする、と考えると分かりやすいです。

10-3. XMLファイルが読み込めない原因は?

XMLファイルが読み込めない主な原因は、ファイルパスの間違い、ファイルが存在しない、XMLの形式が不正、文字コードの不一致、アクセス権限の不足などです。

まずは、指定したパスにファイルが存在するか確認しましょう。次に、XMLのタグが正しく閉じられているか、ルート要素が1つだけか、文字コードが合っているかを確認します。

C#側では、try-catch を使って例外内容を確認すると原因を特定しやすくなります。

10-4. XPathとLINQはどちらを使うべき?

XPathは、XMLの階層をパスで指定して検索する方法です。複雑なXML構造から特定のノードを探す場合に便利です。

LINQは、C#のコードとして条件検索や変換処理を書ける方法です。データの一覧取得、条件抽出、オブジェクトへの変換などに向いています。

既存コードでXPathが使われているならXPath、新規開発で読みやすさを重視するならLINQ to XMLを選ぶとよいでしょう。

10-5. 大きなXMLファイルを扱う場合はどうする?

大きなXMLファイルを扱う場合、XmlDocumentやXDocumentで全体を読み込むとメモリ使用量が大きくなる可能性があります。

そのような場合は、XmlReader を使ってXMLを先頭から順番に読み込む方法が適しています。

C#
using XmlReader reader = XmlReader.Create("large.xml");

while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element && reader.Name == "item")
{
string id = reader.GetAttribute("id");
Console.WriteLine(id);
}
}

すべてのXMLをメモリに保持する必要がないため、大容量ファイルでも効率よく処理できます。

10-6. C#でXMLを簡単に読み書きするならどの方法がおすすめ?

C#でXMLを簡単に読み書きしたい場合は、LINQ to XMLがおすすめです。XDocumentXElement を使うことで、XMLの読み込み、検索、作成、更新を分かりやすく書けます。

特に初心者の場合、XmlDocumentよりもLINQ to XMLの方がコードの見通しがよく、C#らしい書き方ができます。

ただし、XPathを使いたい場合や既存コードがXmlDocumentで書かれている場合は、XmlDocumentを選ぶのも自然です。

まとめ

C#でXMLを扱う方法には、主にXmlDocumentとLINQ to XMLがあります。

XmlDocumentは、従来から使われているXML操作方法で、XPathを使った検索に向いています。既存のC#プロジェクトや古い.NET環境では、XmlDocumentを使う場面も多いです。

一方、LINQ to XMLは、XDocumentXElement を使ってXMLを直感的に操作できる方法です。LINQで条件検索や一覧取得ができるため、新規開発や初心者の学習には特におすすめです。

C# XML処理では、要素、属性、テキスト、階層構造を理解し、読み込み、解析、作成、更新、削除の基本を押さえることが重要です。また、実務ではnull参照エラー、文字コード、XML形式の不正、外部XMLのセキュリティにも注意する必要があります。

まずはLINQ to XMLで基本的な読み書きを学び、必要に応じてXmlDocumentやXPath、XmlReaderも使い分けることで、C#でXMLを安全かつ効率的に扱えるようになります。