LINQ to XMLを使ったXMLファイルの書き出し - C#

LINQ To XMLを用いたXMLファイルの書き出し方法を紹介します。
XMLファイルを書き出すにあたり、はじめにXMLの構造を作成します。XElementクラスを用いてXMLの構造を作成します。
XElementのコンストラクタのひとつは
XElement(XName, Object)
という構造になっており、第二引数に与えたObjectを子ノードとして持つノードを作成できます。
下記コード例のようにXElementのコンストラクタをネストして記述することで階層を持ったXMLの構造が作成できます。(末端の葉ノードではネストせずにノードの値を記述します。)

コード例

private void button11_Click(object sender, EventArgs e)
{
  XElement root =
    new XElement("root",
      new XElement("item",
        new XElement("Code", "CD-010"),
        new XElement("Name", "Penguin Cookie"),
        new XElement("Price", "250")
      ),
      new XElement("item",
        new XElement("Code", "CD-023"),
        new XElement("Name", "Whale Candy"),
        new XElement("Price", "80")
      ),
      new XElement("item",
        new XElement("Code", "CD-046"),
        new XElement("Name", "Bear Potato"),
        new XElement("Price", "180")
      )
    );

  FileStream fs = new FileStream(textBox3.Text, FileMode.Create);
  root.Save(fs);
  fs.Close();
  fs.Dispose();
}

実行結果 (出力XMLファイル)

<?xml version="1.0" encoding="utf-8"?>
<root>
  <item>
    <Code>CD-010</Code>
    <Name>Penguin Cookie</Name>
    <Price>250</Price>
  </item>
  <item>
    <Code>CD-023</Code>
    <Name>Whale Candy</Name>
    <Price>80</Price>
  </item>
  <item>
    <Code>CD-046</Code>
    <Name>Bear Potato</Name>
    <Price>180</Price>
  </item>
</root>

空要素を含む例

空要素を作成する場合は
new XElement("Empty"),
のような引数を1つしかとらないXElementのコンストラクタを利用します。

コード例

private void button12_Click(object sender, EventArgs e)
{
  XElement root =
    new XElement("root",
      new XElement("item",
        new XElement("Empty"),
        new XElement("Code", "CD-010"),
        new XElement("Name", "Penguin Cookie"),
        new XElement("Price", "250")
      ),
      new XElement("item",
        new XElement("Code", "CD-023"),
        new XElement("Name", "Whale Candy"),
        new XElement("Price", "80")
      ),
      new XElement("item",
        new XElement("Empty"),
        new XElement("Code", "CD-046"),
        new XElement("Name", "Bear Potato"),
        new XElement("Price", "180")
      )
    );
  FileStream fs = new FileStream(textBox3.Text, FileMode.Create);
  root.Save(fs);
  fs.Close();
  fs.Dispose();
}

実行結果

<?xml version="1.0" encoding="utf-8"?>
<root>
  <item>
    <Empty />
    <Code>CD-010</Code>
    <Name>Penguin Cookie</Name>
    <Price>250</Price>
  </item>
  <item>
    <Code>CD-023</Code>
    <Name>Whale Candy</Name>
    <Price>80</Price>
  </item>
  <item>
    <Empty />
    <Code>CD-046</Code>
    <Name>Bear Potato</Name>
    <Price>180</Price>
  </item>
</root>

クローンとアタッチ

TREE 1

□ root (XElement)
 └□ item1 (XElement)

TREE 2

□ item2 (XElement)

TREE 3

□ root (XElement)
 ├□ TREE 1のitem1
 └□ TREE 2のitem2
というツリーがあったとき
TREE 1のitem1とTREE 3のitem1はクローンされたコピーになりますが、
TREE 3のitem2とTREE 2のitem2は同じXElementのインスタンスになります。
これは、新しいノード(XElement)に既に親があり、別の XML ツリーの一部となっている場合は、新しいノード(XElement)が複製され、新しく複製されたコンテンツが XML ツリーにアタッチされるためです。

コード例

private void button14_Click(object sender, EventArgs e)
{
  XElement rootElem1 = new XElement("root", 
    new XElement("item1", 1)
  );

  XElement item2 = new XElement("item2", 2);

  XElement rootElem2 = new XElement("root",
      rootElem1.Element("item1"),
      item2
  );

  if (rootElem1.Element("item1") == rootElem2.Element("item1")) {
    textBox4.Text += "rootElem1のitem1 と rootElem2のitem1 は同じものです。\r\n";
  }
  else {
    textBox4.Text += "rootElem1のitem1 と rootElem2のitem1 はクローンコピーです。\r\n";
  }

  if (item2 == rootElem2.Element("item2")) {
    textBox4.Text += "item2 と rootElem2のitem2 は同じものです。\r\n";
  }
  else {
    textBox4.Text += "item2 と rootElem2のitem2 はクローンコピーです。\r\n";
  }
}

実行結果

rootElem1のitem1 と rootElem2のitem1 はクローンコピーです。
item2 と rootElem2のitem2 は同じものです。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2011-01-30
iPentec all rights reserverd.