読者です 読者をやめる 読者になる 読者になる

いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

Linq入門記-55 (LINQ to XML, XDocument, XElement.ctor, 関数型構築)

C# Linq


今回は、LINQ to XMLの特徴の一つであるである関数型構築についてメモ。

以前の内容は以下から見れます。よろしければご参照くださいませ。

サンプルコードは、まとめてCodePlexにアップしてます。


LINQ to XMLには、関数型構築という仕組みがあり
XMLツリーを簡単に構築する事が出来るようになっています。
関数型構築って何?という感じですが、イメージとしてXElementクラスの
コンストラクタを利用して、XMLの要素を数珠つなぎで設定していく方法です。


以下のような感じです。

var doc = new XDocument
          (
            new XElement
            (
              "RootElement",
              new XElement("ChildElement", "ChildValue1"),
              new XElement("ChildElement", "ChildValue2"),
              new XElement("ChildElement", "ChildValue3"),
            )
          );

XDocumentのコンストラクタに指定しているXElementがルート要素となります。
XDocumentはXMLの仕様に従い、ルート要素を一つしか指定出来ません。


上記は以下のXMLツリーを構築します。

<RootElement>
  <ChildElement>ChildValue1</ChildElement>
  <ChildElement>ChildValue2</ChildElement>
  <ChildElement>ChildValue3</ChildElement>
</RootElement>


子要素を指定する場合、以下の規則で処理されます。
(http://msdn.microsoft.com/ja-jp/library/vstudio/bb387089.aspx)

  • 文字列はテキストコンテンツとして扱われる
  • XElementは子要素として扱われる
  • XAttributeは属性要素として扱われる
  • XProcessingInstruction, XComment, XTextは子コンテンツとして扱われる
  • IEnumerableは列挙され、その結果にこれらの規則が再帰的に適用される
  • 上記以外のその他の型の場合、ToStringメソッドが呼ばれテキストコンテンツとして扱われる

当然、構築部分でもLINQが利用出来ます。
以下は、同じXMLツリーが構築されます。

var doc = new XDocument
          (
            new XElement
            (
              "RootElement",
              from   value in new []{ "ChildValue1", "ChildValue2", "ChildValue3" }
              select new XElement("ChildElement", value)
            )
          );


以下、サンプルです。

  #region LinqSamples-52
  /// <summary>
  /// LINQ to XMLのサンプルです。
  /// </summary>
  /// <remarks>
  /// XDocumentオブジェクトを関数型構築するサンプルです。
  /// </remarks>
  public class LinqSamples52 : IExecutable
  {
    public void Execute()
    {
      //
      // XDocumentは複数のコンストラクタを持っているが
      // 以下を利用すると、関数型構築が行える.
      // 関数型構築とは、単一のステートメントでXMLツリーを作成するための機能である。
      // (XElementクラスのコンストラクタを用いる)
      // 
      // public XDocument(object[])
      // public XDocument(XDeclaration, object[])
      //
      // XDocumentを起点として関数型構築を行う場合
      // ルート要素となるXElementを作成し、その子要素に
      // 様々な要素を設定する.
      //
      // 例:
      // var doc = new XDocument
      //           (
      //             new XElement
      //             (
      //               "RootElement",
      //               new XElement("ChildElement", "ChildValue1"),
      //               new XElement("ChildElement", "ChildValue2"),
      //               new XElement("ChildElement", "ChildValue3")
      //             )
      //           );
      //
      // 上記例は、以下のXMLツリーを構築する.
      // <RootElement>
      //   <ChildElement>ChildValue1</ChildElement>
      //   <ChildElement>ChildValue2</ChildElement>
      //   <ChildElement>ChildValue3</ChildElement>
      // </RootElement>
      //
      var doc = MakeDocument();
      Console.WriteLine(doc);
    }
    
    XDocument MakeDocument()
    {
      var doc   = new XDocument
                  (
                    new XDeclaration("1.0", "utf-8", "yes"),
                    new XElement("Persons", MakePersonElements())
                  );
    
      return doc;
    }
    
    IEnumerable<XElement> MakePersonElements()
    {
      var names = new []{ "foo", "bar", "baz" };
      var query = from   name in names
                  select new XElement
                         (
                           "Person",
                           new XAttribute("name", name),
                           string.Format("VALUE-{0}", name)
                         );
      
      return query;
    }
  }
  #endregion


実行結果は以下のようになります。

  
    VALUE-foo
    VALUE-bar
    VALUE-baz
  


以下、参照リソースです。

================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。