C#のXElementとは?XMLの作成・取得・更新・保存を初心者向けに徹底解説
はじめに
C#でXMLを扱う方法はいくつかありますが、初心者でも比較的わかりやすく、少ないコードでXMLを操作できるのがXElementです。
XElementを使うと、次のような処理を簡潔に記述できます。
XML要素の作成
子要素や属性の追加
XMLファイルからのデータ取得
要素の値や属性の更新
要素の追加・削除
XMLファイルへの保存
特に、LINQと組み合わせてXML内のデータを検索できる点が大きな特徴です。
この記事では、C#のXElementについて、XMLの作成方法を中心に、取得・更新・保存まで初心者向けに解説します。
1. C#のXElementとは
1-1. XElementはXML要素を表すLINQ to XMLのクラス
XElementは、XML文書内の「要素」を表すクラスです。.NETが提供するSystem.Xml.Linq名前空間に含まれており、LINQ to XMLを使ってXMLを操作する際に利用します。
たとえば、次のXMLがあるとします。
XML<book>
<title>C#入門</title>
<price>2500</price>
</book>
このXMLでは、book、title、priceがそれぞれXML要素です。C#では、それぞれの要素をXElementオブジェクトとして扱えます。
C#XElement book = new XElement(
"book",
new XElement("title", "C#入門"),
new XElement("price", 2500)
);
XElementでは、XMLの構造をC#のオブジェクトとして直感的に記述できます。
また、LINQのメソッドを利用して、特定の要素を検索したり、条件に一致する要素だけを取得したりすることも可能です。
1-2. XElementでできること
XElementを使うと、主に次のようなXML操作を行えます。
XML要素の作成
C#XElement element = new XElement("name", "山田太郎");
子要素の追加
C#element.Add(new XElement("age", 30));
属性の追加
C#element.Add(new XAttribute("id", 1));
子要素の取得
C#XElement? title = element.Element("title");
要素の値を更新
C#element.SetElementValue("age", 31);
属性値を更新
C#element.SetAttributeValue("id", 2);
XMLファイルの読み込み
C#XElement root = XElement.Load("data.xml");
XMLファイルへの保存
C#element.Save("data.xml");
XMLの作成から読み込み、検索、更新、削除、保存まで、一般的な操作をXElementだけで実装できます。
1-3. XElementとXMLDocument・XmlElementの違い
C#でXMLを扱うクラスには、XElementのほかにXmlDocumentやXmlElementがあります。
XmlDocumentとXmlElementは、従来から利用されているDOM形式のXML操作クラスです。一方、XElementはLINQ to XMLとして提供されており、LINQを利用した検索やデータ加工に適しています。
| 比較項目 | XElement | XmlDocument・XmlElement |
|---|---|---|
| 名前空間 | System.Xml.Linq | System.Xml |
| XMLの作成 | 宣言的に記述できる | ノードを順番に作成する |
| データ検索 | LINQを使用できる | XPathやDOM APIを使用する |
| コード量 | 比較的少ない | 多くなりやすい |
| 初心者の扱いやすさ | 比較的わかりやすい | DOMの知識が必要 |
| 既存システムとの互換性 | LINQ to XML向け | 従来のXML処理で広く使用 |
たとえば、XmlDocumentで要素を作成する場合は、次のように記述します。
C#XmlDocument document = new XmlDocument();
XmlElement book = document.CreateElement("book");
XmlElement title = document.CreateElement("title");
title.InnerText = "C#入門";
book.AppendChild(title);
document.AppendChild(book);
同じXMLをXElementで作成すると、より簡潔になります。
C#XElement book = new XElement(
"book",
new XElement("title", "C#入門")
);
新しくXML処理を実装する場合や、LINQを利用してXMLを検索したい場合は、XElementが有力な選択肢です。
一方、既存のプログラムがXmlDocumentを使用している場合や、特定のDOM APIに依存している場合は、XmlDocumentを継続して利用することもあります。
1-4. XElementを利用するためのusing宣言と.NET環境
XElementを利用するには、ソースコードの先頭に次のusing宣言を追加します。
C#using System.Xml.Linq;
使用例は次のとおりです。
C#using System;
using System.Xml.Linq;
class Program
{
static void Main()
{
XElement message = new XElement("message", "Hello XML");
Console.WriteLine(message);
}
}
実行結果は次のようになります。
XML<message>Hello XML</message>
XElementは、LINQ to XMLをサポートする.NET Framework 3.5以降や、現在の.NET環境で利用できます。
SDKスタイルの一般的な.NETプロジェクトでは、通常、追加パッケージをインストールする必要はありません。System.Xml.Linqをusingで読み込むだけで利用できます。
プロジェクトの設定によって暗黙的なusingが有効になっている場合でも、System.Xml.Linqが読み込まれていなければ明示的に追加してください。
2. XElementの基本的な使い方
2-1. XElementのインスタンスを作成する
XElementのインスタンスは、new XElement()を使って作成します。
基本構文は次のとおりです。
C#XElement 要素を格納する変数 = new XElement("要素名");
たとえば、userという名前のXML要素を作成する場合は、次のように記述します。
C#XElement user = new XElement("user");
Console.WriteLine(user);
出力結果は次のとおりです。
XML<user />
要素に値や子要素が設定されていないため、空要素として出力されます。
XML要素名は文字列で直接指定できますが、内部的にはXNameとして扱われます。そのため、次のようにXName型を使って指定することも可能です。
C#XName elementName = "user";
XElement user = new XElement(elementName);
通常のXMLを作成するだけであれば、文字列で要素名を指定する方法で問題ありません。
2-2. 要素名と値を指定してXML要素を作成する
XElementのコンストラクターに要素名と値を渡すと、値を持つXML要素を作成できます。
C#XElement name = new XElement("name", "山田太郎");
Console.WriteLine(name);
出力結果は次のとおりです。
XML<name>山田太郎</name>
文字列だけでなく、数値や真偽値、日付なども指定できます。
C#XElement age = new XElement("age", 30);
XElement isActive = new XElement("isActive", true);
XElement createdAt = new XElement("createdAt", DateTime.Now);
複数の要素を出力する例は次のとおりです。
C#Console.WriteLine(age);
Console.WriteLine(isActive);
Console.WriteLine(createdAt);
XElementは、指定された値をXMLで表現できる文字列に変換します。
要素の値を取得する場合は、Valueプロパティを使用します。
C#XElement age = new XElement("age", 30);
string value = age.Value;
Console.WriteLine(value);
実行結果は次のとおりです。
30
取得した値を整数として扱う場合は、キャストまたは変換処理を行います。
C#int ageValue = (int)age;
XMLの内容が不正である可能性がある場合は、int.TryParseを使用すると安全です。
C#if (int.TryParse(age.Value, out int ageValue))
{
Console.WriteLine(ageValue);
}
2-3. 子要素を含む階層構造を作成する
XMLでは、要素の中に別の要素を配置して階層構造を作れます。
XElementでは、コンストラクターの引数に別のXElementを指定することで、子要素を作成できます。
C#XElement user = new XElement(
"user",
new XElement("name", "山田太郎"),
new XElement("age", 30),
new XElement("email", "yamada@example.com")
);
Console.WriteLine(user);
出力結果は次のとおりです。
XML<user>
<name>山田太郎</name>
<age>30</age>
<email>yamada@example.com</email>
</user>
さらに深い階層構造も作成できます。
C#XElement user = new XElement(
"user",
new XElement("name", "山田太郎"),
new XElement(
"address",
new XElement("postalCode", "100-0001"),
new XElement("prefecture", "東京都"),
new XElement("city", "千代田区")
)
);
作成されるXMLは次のとおりです。
XML<user>
<name>山田太郎</name>
<address>
<postalCode>100-0001</postalCode>
<prefecture>東京都</prefecture>
<city>千代田区</city>
</address>
</user>
子要素を取得するには、Elementメソッドを使用します。
C#XElement? nameElement = user.Element("name");
if (nameElement != null)
{
Console.WriteLine(nameElement.Value);
}
Elementメソッドは、指定した名前を持つ最初の子要素を返します。対象の要素が存在しない場合はnullを返すため、必要に応じてnullチェックを行いましょう。
複数の子要素を取得する場合は、Elementsメソッドを使用します。
C#IEnumerable<XElement> childElements = user.Elements();
foreach (XElement child in childElements)
{
Console.WriteLine($"{child.Name}: {child.Value}");
}
同じ名前の子要素だけを取得することも可能です。
C#IEnumerable<XElement> items = user.Elements("item");
2-4. XAttributeで属性を追加する
XML要素に属性を追加する場合は、XAttributeクラスを使用します。
C#XElement user = new XElement(
"user",
new XAttribute("id", 1),
new XElement("name", "山田太郎")
);
Console.WriteLine(user);
出力結果は次のとおりです。
XML<user id="1">
<name>山田太郎</name>
</user>
複数の属性を指定することもできます。
C#XElement user = new XElement(
"user",
new XAttribute("id", 1),
new XAttribute("status", "active"),
new XElement("name", "山田太郎")
);
作成されるXMLは次のとおりです。
XML<user id="1" status="active">
<name>山田太郎</name>
</user>
属性値を取得するには、Attributeメソッドを使用します。
C#XAttribute? idAttribute = user.Attribute("id");
if (idAttribute != null)
{
Console.WriteLine(idAttribute.Value);
}
明示的なキャストを利用すると、より簡潔に取得できます。
C#int? id = (int?)user.Attribute("id");
string? status = (string?)user.Attribute("status");
属性を追加または更新する場合は、SetAttributeValueメソッドが便利です。
C#user.SetAttributeValue("status", "inactive");
指定した属性が存在すれば値が更新され、存在しなければ新しい属性が追加されます。
属性を削除する場合は、値にnullを指定します。
C#user.SetAttributeValue("status", null);
XAttributeを直接取得して、Removeメソッドで削除することもできます。
C#user.Attribute("status")?.Remove();
2-5. XDocumentとの違いと使い分け
XElementとともによく使われるクラスにXDocumentがあります。
XElementは1つのXML要素を表すクラスです。一方、XDocumentはXML文書全体を表します。
XDocumentを使うと、XML宣言やコメントなどを含む文書全体を作成できます。
C#XDocument document = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(
"users",
new XElement(
"user",
new XAttribute("id", 1),
new XElement("name", "山田太郎")
)
)
);
Console.WriteLine(document);
作成されるXMLの内容は次のとおりです。
XML<?xml version="1.0" encoding="utf-8"?>
<users>
<user id="1">
<name>山田太郎</name>
</user>
</users>
使い分けの目安は次のとおりです。
XML要素やXMLの一部分だけを扱う場合は
XElementXML宣言を含む文書全体を扱う場合は
XDocument既存のXMLファイルのルート要素だけが必要な場合は
XElement.LoadXML宣言や文書全体の構造が必要な場合は
XDocument.Load
ただし、XElementだけでもルート要素を作成し、XMLファイルとして保存できます。
C#XElement root = new XElement(
"users",
new XElement(
"user",
new XElement("name", "山田太郎")
)
);
root.Save("users.xml");
XML宣言やコメント、処理命令などを細かく管理する必要がなければ、XElementだけで十分なケースも多くあります。
3. XElementでXMLを作成する方法
3-1. コンストラクターを使ってXMLを作成する
XElementのコンストラクターを利用すると、XML全体の構造をまとめて記述できます。
次の例では、複数の商品情報を含むXMLを作成しています。
C#XElement products = new XElement(
"products",
new XElement(
"product",
new XAttribute("id", 1),
new XElement("name", "キーボード"),
new XElement("price", 5000),
new XElement("stock", 10)
),
new XElement(
"product",
new XAttribute("id", 2),
new XElement("name", "マウス"),
new XElement("price", 3000),
new XElement("stock", 20)
)
);
Console.WriteLine(products);
作成されるXMLは次のとおりです。
XML<products>
<product id="1">
<name>キーボード</name>
<price>5000</price>
<stock>10</stock>
</product>
<product id="2">
<name>マウス</name>
<price>3000</price>
<stock>20</stock>
</product>
</products>
コンストラクターを使う方法には、XMLの完成形を見ながらコードを記述できるというメリットがあります。
また、配列やリストからXMLを作成することもできます。
C#var productList = new[]
{
new { Id = 1, Name = "キーボード", Price = 5000 },
new { Id = 2, Name = "マウス", Price = 3000 },
new { Id = 3, Name = "モニター", Price = 25000 }
};
XElement products = new XElement(
"products",
productList.Select(product =>
new XElement(
"product",
new XAttribute("id", product.Id),
new XElement("name", product.Name),
new XElement("price", product.Price)
)
)
);
LINQのSelectメソッドを組み合わせることで、オブジェクトの一覧をXML要素へ変換できます。
作成したXMLをファイルへ保存する場合は、Saveメソッドを使用します。
C#products.Save("products.xml");
指定したパスに同名のファイルが存在する場合は、基本的に上書きされます。保存先のディレクトリが存在しない場合は例外が発生するため、必要に応じて事前にディレクトリを作成してください。
C#string directoryPath = "output";
string filePath = Path.Combine(directoryPath, "products.xml");
Directory.CreateDirectory(directoryPath);
products.Save(filePath);
保存時の文字コードを明示的に指定したい場合は、XmlWriterを利用できます。
C#using System.Text;
using System.Xml;
using System.Xml.Linq;
XmlWriterSettings settings = new XmlWriterSettings
{
Encoding = new UTF8Encoding(false),
Indent = true
};
using XmlWriter writer = XmlWriter.Create("products.xml", settings);
products.Save(writer);
3-2. Addメソッドで要素や属性を追加する
Addメソッドを使うと、作成済みのXElementへ後から子要素や属性を追加できます。
まず、ルート要素を作成します。
C#XElement products = new XElement("products");
次に、商品要素を追加します。
C#XElement product = new XElement("product");
product.Add(new XAttribute("id", 1));
product.Add(new XElement("name", "キーボード"));
product.Add(new XElement("price", 5000));
products.Add(product);
作成されるXMLは次のとおりです。
XML<products>
<product id="1">
<name>キーボード</name>
<price>5000</price>
</product>
</products>
Addメソッドには、複数の要素をまとめて渡すこともできます。
C#XElement product = new XElement("product");
product.Add(
new XAttribute("id", 1),
new XElement("name", "キーボード"),
new XElement("price", 5000),
new XElement("stock", 10)
);
複数の商品を繰り返し処理で追加することも可能です。
C#var productList = new[]
{
new { Id = 1, Name = "キーボード", Price = 5000 },
new { Id = 2, Name = "マウス", Price = 3000 }
};
XElement products = new XElement("products");
foreach (var item in productList)
{
XElement product = new XElement(
"product",
new XAttribute("id", item.Id),
new XElement("name", item.Name),
new XElement("price", item.Price)
);
products.Add(product);
}
Addメソッドは、条件に応じて要素を追加したい場合にも便利です。
C#XElement product = new XElement(
"product",
new XAttribute("id", 1),
new XElement("name", "キーボード")
);
bool hasDiscount = true;
if (hasDiscount)
{
product.Add(new XElement("discount", 500));
}
XMLファイルを読み込む
保存済みのXMLファイルを読み込む場合は、XElement.Loadメソッドを使用します。
C#XElement products = XElement.Load("products.xml");
Console.WriteLine(products);
XML文字列から作成する場合は、XElement.Parseメソッドを使用します。
C#string xml = """
<products>
<product id="1">
<name>キーボード</name>
<price>5000</price>
</product>
</products>
""";
XElement products = XElement.Parse(xml);
外部から受け取った文字列が正しいXML形式でない場合、Parseメソッドは例外を発生させます。実際のアプリケーションでは、必要に応じて例外処理を追加しましょう。
C#try
{
XElement products = XElement.Parse(xml);
}
catch (System.Xml.XmlException ex)
{
Console.WriteLine($"XMLの形式が正しくありません: {ex.Message}");
}
特定の要素を取得する
Elementメソッドを使用すると、直接の子要素から最初に一致する要素を取得できます。
C#XElement? product = products.Element("product");
XElement? name = product?.Element("name");
Console.WriteLine(name?.Value);
複数のproduct要素を取得する場合は、Elementsメソッドを使用します。
C#IEnumerable<XElement> productElements = products.Elements("product");
foreach (XElement item in productElements)
{
string? id = (string?)item.Attribute("id");
string? name = (string?)item.Element("name");
int? price = (int?)item.Element("price");
Console.WriteLine($"ID: {id}, 商品名: {name}, 価格: {price}");
}
LINQを使って条件に一致する要素だけを取得することもできます。
C#IEnumerable<XElement> expensiveProducts =
products.Elements("product")
.Where(product => (int?)product.Element("price") >= 5000);
foreach (XElement product in expensiveProducts)
{
Console.WriteLine((string?)product.Element("name"));
}
直接の子要素だけでなく、すべての子孫要素から検索する場合はDescendantsメソッドを使用します。
C#IEnumerable<XElement> names = products.Descendants("name");
foreach (XElement name in names)
{
Console.WriteLine(name.Value);
}
要素の値を更新する
既存要素の値は、Valueプロパティで更新できます。
C#XElement? priceElement = products
.Elements("product")
.FirstOrDefault(product => (int?)product.Attribute("id") == 1)?
.Element("price");
if (priceElement != null)
{
priceElement.Value = "5500";
}
SetElementValueメソッドを使う方法もあります。
C#XElement? product = products
.Elements("product")
.FirstOrDefault(product => (int?)product.Attribute("id") == 1);
product?.SetElementValue("price", 5500);
SetElementValueは、対象の子要素が存在する場合は値を更新し、存在しない場合は新しい子要素を追加します。
C#product?.SetElementValue("stock", 15);
値にnullを指定すると、対象の子要素を削除できます。
C#product?.SetElementValue("stock", null);
要素を削除する
特定の要素を削除する場合は、Removeメソッドを使用します。
C#XElement? productToRemove = products
.Elements("product")
.FirstOrDefault(product => (int?)product.Attribute("id") == 2);
productToRemove?.Remove();
条件に一致する複数の要素を削除する場合は、対象を一度リストに変換すると安全です。
C#List<XElement> productsToRemove = products
.Elements("product")
.Where(product => (int?)product.Element("price") < 4000)
.ToList();
productsToRemove.Remove();
列挙中の要素を直接変更すると、意図しない動作や例外につながる場合があります。複数要素を削除する際は、ToListで検索結果を確定してから削除する方法がわかりやすいでしょう。
更新したXMLを保存する
要素の追加や更新、削除を行った後は、Saveメソッドで変更内容をファイルへ保存します。
C#products.Save("products.xml");
読み込みから更新、保存までをまとめると、次のようになります。
C#using System.Linq;
using System.Xml.Linq;
XElement products = XElement.Load("products.xml");
XElement? product = products
.Elements("product")
.FirstOrDefault(item => (int?)item.Attribute("id") == 1);
if (product != null)
{
product.SetElementValue("price", 5500);
product.SetAttributeValue("updated", true);
}
products.Save("products.xml");
このコードでは、id属性が1の商品を取得し、価格と属性を更新した後、同じXMLファイルへ保存しています。
まとめ
C#のXElementは、XML要素をオブジェクトとして扱うためのLINQ to XMLのクラスです。
XElementを使うことで、要素や属性を含むXMLを直感的に作成できます。また、Element、Elements、DescendantsなどのメソッドやLINQを利用して、必要なデータを簡潔に取得できます。
XML操作でよく利用するメソッドは次のとおりです。
| 操作 | 主な方法 |
|---|---|
| 要素を作成する | new XElement() |
| 属性を作成する | new XAttribute() |
| 要素や属性を追加する | Add() |
| 子要素を取得する | Element()、Elements() |
| 子孫要素を取得する | Descendants() |
| 属性を取得する | Attribute() |
| 要素を追加・更新する | SetElementValue() |
| 属性を追加・更新する | SetAttributeValue() |
| 要素や属性を削除する | Remove() |
| XMLファイルを読み込む | XElement.Load() |
| XML文字列を読み込む | XElement.Parse() |
| XMLファイルへ保存する | Save() |
XMLの一部分やルート要素を扱う場合はXElement、XML宣言を含む文書全体を管理する場合はXDocumentを利用するのが基本です。
まずはXElementのコンストラクターで簡単なXMLを作成し、Add、Element、SetElementValue、Saveといった基本的なメソッドから使い方を身につけていきましょう。

