エンジニアの将来って?

現在7年目のCOBOL→Java→C#エンジニアが、将来への考えや勉強のアウトプット、たまに腎臓について書くブログです

【C#】xmlを新規作成し書き込む、XmlWriterを解説します

こんにちは。たいら(@tairaengineer2)です。
この記事では、C#でxmlを新規作成し書き込むXmlWriterについて解説します。

スポンサーリンク

 

前提条件

この記事では、Visual Studio 2017 Communityを使っています。
インストールの仕方は、下の記事をご参考ください。

www.tairax.com

XmlWriterについて

C#でxmlを新規作成する場合は、XmlWriterを使う、とざっくり覚えておけばOKだと思います!
usingは

using System.Xml;

を使います。

XmlWriter Class
名前空間:System.Xml
XML データが格納されたストリームまたはファイルを、高速かつ非キャッシュで前方のみに生成する方法を提供するライターを表します。
public abstract class XmlWriter : IDisposable

XmlWriter Class (System.Xml) | Microsoft Docsから引用させて頂きました

何を書いているかイマイチなので、実際の書き方を見てみましょう!

解説で使うC#の概要

【sampleXml.xml】というxmlを新規作成し、プログラムでxmlの要素を追加し書き込みます。
その結果をコンソールに表示するプログラムです。
本当に作成して書き込むだけなので

<?xml version="1.0" encoding="utf-8" ?>
<productTable>
  <product>
    <name>幕の内弁当</name>
    <price>498</price>
  </product>
  <product>
    <name>唐揚げ弁当</name>
    <price>398</price>
  </product>
  <product>
    <name>セレブ弁当</name>
    <price>998</price>
  </product>
</productTable>

↑のようにインデントはそろっておらず

<?xml version="1.0" encoding="utf-8"?><sample>AAAA</sample>

のようにすべて1行で書かれているものです。

コンソールプロジェクトを作成するやり方は下の記事をご参考ください。

www.tairax.com

C#サンプルコード

using System;
using System.Xml;

namespace ConsoleApp1
{
    /// <summary>
    /// XMLを書き込むサンプル
    /// </summary>
    class Program
    {
        /// <summary>
        /// メイン
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // 出力する場所を指定
            XmlWriter writer = XmlWriter.Create(@"C:\work\sampleXml.xml");

            // 要素sampleXmlを指定
            writer.WriteStartElement("sampleXml");

            // 要素valueに値を指定
            writer.WriteElementString("value", "AAAA");

            // 要素testを指定(属性あり)
            writer.WriteStartElement("test");
            writer.WriteAttributeString("testID", "123");

            // 要素priceに値を指定
            writer.WriteElementString("price", "47821");

            // 要素testの閉じタグ指定
            writer.WriteEndElement();

            // 要素sampleXmlの閉じタグを指定
            writer.WriteEndElement();

            // xmlに書き込む
            writer.Close();

            Console.WriteLine("xmlに書き込みが完了しました。");
        }
    }
}

実行結果

実行する前に確認することがあります。
それは新規作成する場所にxml無いことです。
あとで詳しく解説しますが、xmlを作成する場所を指定している場所はココです。

XmlWriter writer = XmlWriter.Create(@"C:\work\sampleXml.xml");

workフォルダの中を見てみると

f:id:Tairax:20190611082818p:plain

中身が何もないことが確認できました!
では、実行してみます。

f:id:Tairax:20190611083007p:plain

xmlに書き込みが完了しました。
続行するには何かキーを押してください . . .

実際にxmlが新規作成されたのか確認します。

f:id:Tairax:20190611083626p:plain

実際に新規作成されています!

中身を確認してみましょう。

f:id:Tairax:20190611083846p:plain

<?xml version="1.0" encoding="utf-8"?><sampleXml><value>AAAA</value><test testID="123"><price>47821</price></test></sampleXml>

ちゃんと指定した通りに書き込まれています!

 

スポンサーリンク

 

解説

では、解説します。

  1. 新規作成されたxml全体の構成
  2. xmlを作成するCreateメソッド
  3. xml宣言と整形について
  4. WriteStartElementメソッド
  5. WriteEndElementメソッド

の順番で解説します。

新規作成されたxml全体の構成

先ほども書きましたが、新規作成したxmlは↓です。

<?xml version="1.0" encoding="utf-8"?><sampleXml><value>AAAA</value><test testID="123"><price>47821</price></test></sampleXml>

これだと、どんな構成なのか分かりません。
改行やインデントをつけて分かりやすくすると、↓になります。

f:id:Tairax:20190612222517p:plain

<?xml version="1.0" encoding="utf-8"?>
<sampleXml>
	<value>AAAA</value>
	<test testID="123">
		<price>47821</price>
	</test>
</sampleXml>

xmlの要素の構造は↓になります。

f:id:Tairax:20190612223025p:plain

これをC#プログラムでどのように書いているかと言うと

f:id:Tairax:20190613234639p:plain

こういう風に宣言していました。

Createメソッド

Createメソッドは、XmlWriterのインスタンスを作成できます。
指定できる引数は、数多くあります。
今回のCreateメソッドの役割は、引数で指定されたパスにxmlファイルを作成して書き込みます。

Create(String)
指定されたファイル名を使用して新しい XmlWriter インスタンスを作成します。
public static System.Xml.XmlWriter Create (string outputFileName);

XmlWriter.Create Method (System.Xml) | Microsoft Docsから引用させて頂きました

先ほども書きましたが、新規作成するxmlファイルのパスを指定しているのがココです。

XmlWriter writer = XmlWriter.Create(@"C:\work\sampleXml.xml");

この赤文字の部分のパスで指定した場所に【sampleXml.xml】を新規作成します。

今回は絶対パスで指定していますが、相対パスでもOKです。
絶対パスと相対パスについては以下の記事をご参考ください。

www.tairax.com

パスの前に【@】がついていますが、これは逐語的文字列というものです。

C# のキーワードを識別子として使用できるようにする。
コード要素のプレフィックスとして @ 文字を使用すると、その要素はC# のキーワードではなく、識別子としてコンパイラに解釈されます。

@ - C# リファレンス | Microsoft Docsから引用させて頂きました

xml宣言と整形について

上記のプログラムでは、xml宣言をしてませんが新規作成されたxmlにはxml宣言があります。

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

何故ならXmlWriterは、xml宣言をするようにデフォルトで設定されているからです。

XmlWriterの色々な設定をするXmlWriterSettingsというクラスがあります。

XmlWriterSettings Class
名前空間:System.Xml
XmlWriter メソッドで作成された Create オブジェクトでサポートする一連の機能を指定します。

XmlWriterSettings Class (System.Xml) | Microsoft Docsから引用させて頂きました

この記事で解説しているCreateメソッドでは、XmlWriterSettingsを設定していません。
デフォルトのXmlWriterSettingsには、以下の値が設定されてます。

プロパティ 説明
Encoding 使用するテキスト エンコーディングを指定します。 既定値は、Encoding.UTF8 です。
Indent 要素をインデントするかどうかを示します。 既定値はfalse(インデント設定)。
IndentChars インデントに使用する文字列を指定します。 既定値は 2 つのスペースです。
NewLineChars 改行に使用する文字列を指定します。 既定値は \r\n (キャリッジ リターン、ライン フィード) です。
NewLineHandling 改行文字を処理する方法を指定します。
NewLineOnAttributes 新しい行に属性を書き込むかどうかを示します。 このプロパティを使用するときは、Indent を true に設定する必要があります。 既定値は、false です。
OmitXmlDeclaration XML 宣言を書き込むかどうかを示します。 既定値は、false です。

XmlWriter Class (System.Xml) | Microsoft Docsから引用させて頂きました

デフォルト値なので、以下の設定がされています。

  • インデントの設定なし
  • xml宣言を書き込む

インデントの設定がないので、新規作成されたxmlは1行で表示されています。

ちなみにxml宣言をするためのメソッドは、もちろんあります。
WriteStartDocumentメソッドというメソッドです。

WriteStartDocument()
バージョン "1.0" で XML 宣言を書き込みます。
public override void WriteStartDocument ();

XmlTextWriter.WriteStartDocument Method (System.Xml) | Microsoft Docsから引用させて頂きました

XmlWriterSettingsでxml宣言を書き込むように設定されている状態でWriteStartDocumentメソッドを使った場合でも、xml宣言1行しか出力されません。

どういうことかサンプルプログラムを見てみましょう。

using System;
using System.Xml;

namespace ConsoleApp1
{
    /// <summary>
    /// xml宣言
    /// </summary>
    class Program
    {
        /// <summary>
        /// メイン
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // 出力する場所を指定
            XmlWriter writer = XmlWriter.Create(@"C:\work\xmlDocument.xml");

            // xml宣言
            writer.WriteStartDocument();

            // 要素sampleXmlを指定
            writer.WriteStartElement("sampleXml");

            // 要素valueに値を指定
            writer.WriteElementString("value", "AAAA");

            // 要素sampleXmlの閉じタグを指定
            writer.WriteEndElement();

            // xmlに書き込む
            writer.Close();

            Console.WriteLine("xmlに書き込みが完了しました。");
        }
    }
}

実行して新規作成したxmlを見てみます。

f:id:Tairax:20190614003950p:plain

<?xml version="1.0" encoding="utf-8"?><sampleXml><value>AAAA</value></sampleXml>

このようにXmlWriterSettingsxml宣言が設定されている状態でWriteStartDocumentメソッドを使っても、xml宣言は1行しか表示されません。

WriteStartElementメソッド

WriteStartElementメソッドとは、xmlの要素開始タグを設定するメソッドです。

XmlWriter.WriteStartElement Method
名前空間:System.Xml
派生クラスでオーバーライドされると、指定した開始タグを書き込みます。

WriteStartElementに指定できる引数は3種類あります。

メソッド 説明
WriteStartElement(String) 派生クラスでオーバーライドされると、指定したローカル名の開始タグを書き込みます。
WriteStartElement(String, String) 派生クラスでオーバーライドされると、指定した開始タグを書き込み、指定した名前空間に関連付けます。
WriteStartElement(String, String, String) 派生クラスでオーバーライドされると、指定した開始タグを書き込み、指定した名前空間とプリフィックスに関連付けます。

この記事で使用しているWriteStartElement(String)メソッドで、引数に要素名を指定しています。

WriteStartElement(String)
派生クラスでオーバーライドされると、指定したローカル名の開始タグを書き込みます。
public void WriteStartElement (string localName);

上記の説明はXmlWriter.WriteStartElement Method (System.Xml) | Microsoft Docsから引用させて頂きました

要素を閉じる場合は、WriteEndElementメソッドを使います。

WriteEndElementメソッド

WriteEndElementメソッドとは、xmlの要素終了タグを設定するメソッドです。

XmlWriter.WriteEndElement Method
名前空間:System.Xml
派生クラスでオーバーライドされると、1 つの要素を閉じ、対応する名前空間スコープをポップします。
public abstract void WriteEndElement ();

XmlWriter.WriteEndElement Method (System.Xml) | Microsoft Docsから引用させて頂きました

具体例を交えながら解説します。
WriteEndElementメソッドは、指定したとき最もネストが深いものから閉じていきます。
なので

f:id:Tairax:20190613234639p:plain

先ほど使ったxmlの構造の画像です。
別に引数に閉じたいタグを指定していなくても、ネストが深いものから終了タグが設定されていっています。

まとめ:xmlを新規作成してみよう

以上がxmlを新規作成するXmlWriterについて解説です。

あなたのご参考になったのなら、とても嬉しいです(*´▽`*)
ではでは~(・ω・)ノシ

 

ほかにもC#勉強記事を書いてます。
よければご参考ください。

【Visual Studio】xmlの作り方を解説します

【C#】xmlを読み込む、XDocumentとXElementについて解説します。

 

今までブログで書いたC#の解説記事のまとめは、こちらをご参考ください。

【C#】ブログで書いた文法記事のまとめ