[LINQ][C#] LINQ to XML でXMLの操作方法

[LINQ][C#] LINQ to XML でXMLの操作方法

LINQ to XML とは

LINQ to XML は、.NET Framework プログラミング言語から XML を操作できるようにする、LINQ に対応したメモリ内 XML プログラミング インターフェイスです。 … LINQ to XML の最も重要な利点は、統合言語クエリ (LINQ) と統合されていることです。この統合により、メモリ内の XML ドキュメントに対するクエリを記述して、要素および属性のコレクションを取得できます。

LINQ to XMLを使うことで次のようなことができます。

  • ファイルまたはストリームからのXMLの読み込み
  • ファイルまたはストリームへのXMLのシリアル化
  • LINQ to XMLのメソッドを使った、メモリ内のXMLツリー操作
  • XMLツリーの新規作成
  • LINQを使ったXMLツリーの照会

LINQ to XMLのクラス

MSDN:LINQ to XML クラスの概要

LINQ to XMLは、System.Xml.Linq名前空間内のクラスで実現します。各クラスには頭に”X”がついています。代表的なクラスは次のようなものです。

XElement
LINQ to XML の基礎クラスの一つで、XMLの要素を表します。このクラスを使用することで、要素の作成、要素のコンテンツの変更、子要素の追加、変更、削除、属性の追加、及び要素コンテンツのテキストへのシリアル化を行えます。
XAttribute
XAttributeクラスはXMLの属性を表します。XAttributeはXMLの要素(XElement)に関連付けられている名前と値のペアです。
XDocument
XDocumentクラスは、有効なXMLドキュメントに必要な情報(宣言やコメント)を持つことができます。XDocumentは次の要素を含みます。

  • 1つのXDeclaration。これはXML宣言の部分です。
  • 1つのXElement。これはXMLドキュメントのルートノードに該当します。
  • 任意の数のXProcessingInstruction。これはXML処理命令に該当します。
  • 任意の数のXComment。コメントはルート要素の兄弟となりますが、XMLドキュメントはコメントから始めることはできないので、リストの最初の引数にできません。
  • DTD用の1つのXDocumentType。XMLドキュメント型定義 (DTD) を表します。
XNode
XNodeは、XMLツリーのノードを表す抽象クラスです。子ノードは格納できません。XNodeからは次のクラスが派生します。

  • XText
  • XContainer(抽象クラス)
  • XComment
  • XProcessingInstruction
  • XDocumentType
XContainer
XContainerは、子ノード格納できるノードを表す抽象クラスです。次のクラスが派生します。

  • XElement
  • XDocument
XText
テキストノードを表します。
XComment
XMLコメントを表します。
XProcessingInstruction
XML処理命令を表します。
XDocumentType
XMLドキュメント型定義 (DTD) を表します。

XMLの新規作成と保存

各クラスのコンストラクタを組み合わせて1つのXDocumentを作成し、XDocumentのSaveメソッドでファイルに保存してみます。XDocument, XElementのコンストラクタでは指定した名前と要素を持ったXMLを作成しています。

var xdoc = new XDocument(
    new XDeclaration("1.0", "utf-8", null)
    , new XComment("User情報")
    , new XElement(
        "Users"
        , new XElement(
            "User"
            , new XAttribute("id", "001")
            , new XText("太郎")
        )
        , new XElement(
            "User"
            , new XAttribute("id", "002")
            , new XText("次郎")
        )
        , new XElement(
            "User"
            , new XAttribute("id", "003")
            , new XText("三郎")
        )
    )
);
xdoc.Save(@"user.xml");

user.xml

<?xml version="1.0" encoding="utf-8"?>
<!--User情報-->
<Users>
  <User id="001">太郎</User>
  <User id="002">次郎</User>
  <User id="003">三郎</User>
</Users>

XMLデータの抽出

MSDN:XElement クラス

実際にはXMLファイルを読み込んで操作する機会が多いと思います。上で作ったXMLファイルを操作してみます。LINQ to XMLのメソッドは次のようなものがあります。

メソッド 呼び出し元 戻り値 内容
Nodes XDocument, XElement IEnumerable<XNode> すべての子ノード(XNode)を返す。
Elements XDocument, XElement IEnumerable<XElement> すべての子要素(XElement)のコレクションをドキュメントの順序で返す。引数でXElementの名前を指定することもできる。
Element XDocument, XElement XElement 引数で指定した名前の、ドキュメント順序で先頭の子要素(XElement)を返す。
Ancestors XDocument, XElement IEnumerable<XElement> 先祖要素(XElement)のコレクションを返す。引数で名前を指定することもできる。
Descendants XDocument, XElement IEnumerable<XElement> 子孫要素(XElement)のコレクションを返す。引数で名前を指定することもできる。
DescendantNodes XDocument, XElement IEnumerable<XNode> 子孫ルート(XNode)のコレクションを返す。XElement以外も取得できるのがDescendantsとの違い。
Root XDocument XElement XMLドキュメントのルート要素です。

例えば次のようなHtmlファイルからデータを抽出してみます。

index.html

<!DOCTYPE html>
<html>
  <!--html comment-->
  <head>
    <!--head comment-->
    <title>タイトル</title>
  </head>
  <body>
    <!--body comment-->
    <p>
      <!--p comment-->
      Hello World
    </p>
  </body>
</html>
// ファイルの読み込み
var html = XDocument.Load(@"index.html");
// Bodyタグ要素を取得
var body = html.Root.Element("body");
// pタグ要素を取得
var p = body.Elements("p").First();
// コメントノードをすべて取得
var comments = html.DescendantNodes().OfType<XComment>();

XMLデータの編集

XMLデータを編集するメソッドは次の様な物があります。
これらを一通り使ってみればある程度直観的にXMLを操作できます。

メソッド 内容
Add 指定した内容を子として追加する。
AddFirst 指定した内容を子として、既存の子の内容の先頭に追加する。
AddAfterSelf 現在のノードの直後(同レベル)に指定した内容を追加する。
AddBeforeSelf 現在のノードの直前(同レベル)に指定した内容を追加する。
Remove 現在のノードを親から削除する。
RemoveAll 現在のXElementから子ノード及び属性を削除する。
RemoveNodes 現在のXElement, XDocumentから子ノードを削除する。
ReplaceAll 現在の要素から子ノードを、指定した内容で置き換えます。
ReplaceWith 現在のノードを、指定した内容で置き換えます。
SetValue 現在の要素の値を設定する。
SetAttributeValue 属性の値を設定、属性の追加または削除する。

XMLの操作のサンプルを次に示します。

user.xml

<?xml version="1.0" encoding="utf-8"?>
<Users>
  <User id="001">
    太郎
  </User>
  <User id="002">
    次郎
  </User>
  <User id="003">
    三郎
  </User>
</Users>
// XML読み込み
var xdoc = XDocument.Load(@"user.xml");
// Users要素
var users = xdoc.Element("Users");
// id = 003 のユーザー(三郎)を削除
var saburo = users.Elements("User")
    .Where(x => x.Attribute("id").Value == "003")
    .FirstOrDefault();
saburo.Remove();
// ユーザー要素(花子)を追加
users.Add(new XElement("User", "花子", new XAttribute("id", "101")));
// 修正した内容で保存
xdoc.Save(@"user_update.xml");

Linqカテゴリの最新記事