2016-02-28T12:07:31の更新内容

programming/netfx/xml/0_generate_write/index.wiki.txt

current previous
1,2108 0,0
+
${smdncms:title,XMLの構築・出力}
+
${smdncms:header_title,XMLの構築・出力 (System.Xml.Linq)}
+
${smdncms:keywords,XDocument,XElement,System.Xml.Linq}
+
#msdn(add-reference,System.Xml.Linq.dll)
+
#msdn(add-reference,System.Xml.dll)
+

          
+
#navi(..)
+

          
+
この文書では、&msdn(netfx,ns,System.Xml.Linq){System.Xml.Linq名前空間};のクラス郡を使ってXML文書を構築する方法、またファイルなどに出力する方法ついて扱います。 &msdn(netfx,type,System.Xml.Linq.XDocument){XDocumentクラス};や&msdn(netfx,type,System.Xml.Linq.XElement){XElementクラス};を使ったXMLの構築では、&msdn(netfx,type,System.Xml.XmlDocument){System.Xml.XmlDocumentクラス};を使った場合と比べるとXMLの構造にごく近い形で記述でき、コードが非常に分かりやすくなります。 インターフェイスもシンプルで把握しやすく、目的とするコードを手早く記述することができます。
+

          
+
System.Xml.Linq名前空間のクラスはアセンブリSystem.Xml.Linq.dllに含まれています。 使用する際はSystem.Xml.Linq.dllを参照に追加します。
+

          
+
この文書では、XMLの読み込みと加工、XMLからのデータの読み出し、またLINQ to XMLの機能については扱いません。
+

          
+
#relevantdocs
+

          
+
-[[programming/netfx/tips/unicode_encoding_bom]]
+
-[[programming/netfx/text_format_conversion]]
+
-[[programming/netfx/stream/2_streamreader_streamwriter]]
+
-[[programming/netfx/serialization/2_xmlserializer]]
+
-[[programming/netfx/classlibrary/2_xmldoccomments]]
+
-[[programming/netfx/msbuild]]
+

          
+
#relevantdocs-end
+

          
+
#adunit
+

          
+
*概略
+
&msdn(netfx,ns,System.Xml.Linq){System.Xml.Linq名前空間};のクラス郡を用いてXML文書の構築を行う場合は、&msdn(netfx,type,System.Xml.Linq.XDocument){XDocumentクラス};や&msdn(netfx,type,System.Xml.Linq.XElement){XElementクラス};などを使います。 これらのクラスを入れ子にしていくことで文書構造を構成します。
+

          
+
#code(cs,System.Xml.Linq名前空間のクラス郡を使ってXML文書を構築する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("html",                  // <html>要素
+
        new XAttribute("lang", "ja"),       // lang属性、属性の値に"ja"を指定(lang="ja")
+
        new XElement("head",                // <head>要素
+
          new XElement("title", "タイトル") // <title>要素、要素のテキストとして"タイトル"を指定
+
        ),
+
        new XElement("body",                // <body>要素
+
          new XComment("本文"),             // コメント、<!--本文-->を作成
+
          new XElement("p", "段落"),        // <p>要素、要素のテキストとして"段落"を指定
+
          new XElement("p", 1234567)        // <p>要素、要素のテキストとして値1234567を指定
+
        )
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<html lang="ja">
+
  <head>
+
    <title>タイトル</title>
+
  </head>
+
  <body>
+
    <!--本文-->
+
    <p>段落</p>
+
    <p>1234567</p>
+
  </body>
+
</html>
+
}}
+

          
+
``XDocument``がXML文書、``XElement``が要素を表すクラスとなります。 XElementのコンストラクタでは、``new XElement(&var{要素名};, &var{子ノード};, &var{子ノード};, ...)``のように引数を指定します。 これにより、要素に任意個の子ノードを含めることができます。
+

          
+
子ノードとしてXElementを指定すれば子要素となり、これを入れ子にしていくことで文書構造を定義していくことができます。 XElementではなく文字列を子ノードに指定すれば、テキストノード、つまり要素内のテキストを指定することができます。 また、子ノードとして&msdn(netfx,type,System.Xml.Linq.XAttribute){XAttribute};や&msdn(netfx,type,System.Xml.Linq.XComment){XComment};を含めれば、要素に属性やコメントを付与することができます。
+

          
+

          
+

          
+
生成したXML文書をファイルなどに保存する場合は&msdn(netfx,member,System.Xml.Linq.XDocument.Save){XDocument.Saveメソッド};を使います。
+

          
+
#code(cs,XDocument.Saveメソッドを使って構築したXML文書をファイルに保存する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("html",
+
        new XAttribute("lang", "ja"),
+
        new XElement("head",
+
          new XElement("title", "タイトル")
+
        ),
+
        new XElement("body",
+
          new XElement("p", "本文")
+
        )
+
      )
+
    );
+

          
+
    // XDocumentの内容をtest.xmlに保存する
+
    doc.Save("test.xml");
+
  }
+
}
+
}}
+

          
+
#code(xml,type=output,test.xmlに出力される内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<html lang="ja">
+
  <head>
+
    <title>タイトル</title>
+
  </head>
+
  <body>
+
    <p>本文</p>
+
  </body>
+
</html>
+
}}
+

          
+
#remarks
+
Saveメソッドでの保存時に指定できるオプションについては[[#XDocument.Save]]を参照してください。
+
#remarks-end
+

          
+
#remarks
+
インデントの有無・インデント幅の変更、文字コードの扱いなど、出力時の動作を変更する方法については後述の[[#XmlWriter]]を参照してください。
+
#remarks-end
+

          
+

          
+
*XMLツリーの構築
+
XMLツリーを構築する際には、&msdn(netfx,ns,System.Xml.Linq){System.Xml.Linq名前空間};のクラスを組み合わせて構成します。 以下はその主なクラスです。
+

          
+
|*ノードの種類とSystem.Xml.Linq名前空間のクラス
+
|~ノードの種類・構成要素|~該当するクラス|~解説|h
+
|XML文書|&msdn(netfx,type,System.Xml.Linq.XDocument){XDocument};|-|
+
|要素|&msdn(netfx,type,System.Xml.Linq.XElement){XElement};|[[#XElement_XAttribute_XText]]|
+
|属性|&msdn(netfx,type,System.Xml.Linq.XAttribute){XAttribute};|[[#XElement_XAttribute_XText]]|
+
|テキスト|&msdn(netfx,type,System.Xml.Linq.XText){XText};|[[#XElement_XAttribute_XText]]|
+
|CDATAセクション|&msdn(netfx,type,System.Xml.Linq.XCData){XCData};|[[#XCData]]|
+
|コメント|&msdn(netfx,type,System.Xml.Linq.XComment){XComment};|[[#XComment]]|
+
|XML宣言|&msdn(netfx,type,System.Xml.Linq.XDeclaration){XDeclaration};|[[#XDeclaration]]|
+
|名前空間|&msdn(netfx,type,System.Xml.Linq.XNamespace){XNamespace};|[[#XNamespace]]|
+

          
+

          
+
**要素・属性・テキストノード (XElement・XAttribute・XText) [#XElement_XAttribute_XText]
+
要素を作成するには&msdn(netfx,type,System.Xml.Linq.XElement){XElementクラス};、属性を作成するには&msdn(netfx,type,System.Xml.Linq.XAttribute){XAttributeクラス};を使います。
+

          
+
&msdn(netfx,member,System.Xml.Linq.XElement..ctor){XElementコンストラクタ};・&msdn(netfx,member,System.Xml.Linq.XAttribute..ctor){XAttributeコンストラクタ};の第一引数は要素・属性の名前を指定します。 XElementコンストラクタでは、第二引数以降には子要素・要素のテキスト・属性を指定することができ、それぞれ指定した順序で要素に追加されます。 第二引数以降を指定しなければ''空の要素''(``<&var{element};/>``)が作成されます。 XAttributeコンストラクタでは、第二引数に属性の値を指定します。
+

          
+
|*要素(XElement)と属性(XAttribute)の作成
+
|要素の作成|``new XElement(&var{要素名};, &var{子ノード};, &var{子ノード};, ...)``|
+
|空の要素の作成|``new XElement(&var{要素名};)``|
+
|属性の作成|``new XAttribute(&var{属性名};, &var{属性値};)``|
+

          
+
#column
+
#code(cs,要素・属性・テキストノードの作成){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var element = new XElement("element", // 名前"element"で要素を作成
+
      new XAttribute("attr1", "value1"),  // 名前"attr1"・値"value1"の属性を追加
+
      new XElement("child1"),             // 名前"child1"の要素を追加
+
      "text1",                            // テキスト"text1"を追加
+
      new XAttribute("attr2", "value2"),  // 名前"attr1"・値"value1"の属性を追加
+
      "text2",                            // テキスト"text2"を追加
+
      new XElement("child2")              // 名前"child2"の要素を追加
+
    );
+

          
+
    Console.WriteLine(element);
+
  }
+
}
+
}}
+

          
+

          
+
#prompt(実行結果){{
+
<element attr1="value1" attr2="value2">
+
  <child1 />text1text2<child2 /></element>
+
}}
+

          
+
#column
+
#code(cs,分かりやすさのために変数を用いた左記と同等のコード){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var attr1 = new XAttribute("attr1", "value1");
+
    var child1 = new XElement("child1");
+
    var text1 = "text1";
+
    var attr2 = new XAttribute("attr2", "value2");
+
    var text2 = "text2";
+
    var child2 = new XElement("child2");
+

          
+
    var element = new XElement("element",
+
      attr1,
+
      child1,
+
      text1,
+
      attr2,
+
      text2,
+
      child2
+
    );
+

          
+
    Console.WriteLine(element);
+
  }
+
}
+
}}
+
#column-end
+

          
+
#remarks
+
XDocumentは子要素(XElement)を一つだけ持つことができます。 XMLではルート要素(他の要素に格納されない最上位の要素)は常に1つだけです。 複数のルート要素を持たせることはできません。 XDocumentのルート要素は&msdn(netfx,member,System.Xml.Linq.XDocument.Root){XDocument.Rootプロパティ};を使って取得することができます。
+
#remarks-end
+

          
+

          
+

          
+
XElementコンストラクタの第二引数以降に文字列を指定すると、それが要素のテキストノードとして格納されます。 一方、テキストノードを作成するために&msdn(netfx,type,System.Xml.Linq.XText){XTextクラス};を用いることもできます。 XElementコンストラクタの引数に文字列を指定した場合は、それが自動的にXTextへと変換され、XElementの子ノードとして追加されます。
+

          
+
|*テキストノード(XText)の作成
+
|文字列を使った作成|``new XElement(&var{要素名};, &var{"テキスト"};, &var{"テキスト"};, ...)``|
+
|XTextを使った作成|``new XElement(&var{要素名};, new XText(&var{"テキスト"};), new XText(&var{"テキスト"};), ...)``|
+

          
+

          
+
したがって、以下のコードはどちらも同じXMLツリーを生成します。
+

          
+
#column
+
#code(cs,文字列を使ってテキストノードを記述する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var element = new XElement("element",
+
      new XElement("child1", "text1" /*テキストノード*/),
+
      new XElement("child2", "text2" /*テキストノード*/),
+
      "text3" /*テキストノード*/
+
    );
+

          
+
    Console.WriteLine(element);
+
  }
+
}
+
}}
+
#column
+
#code(cs,XTextクラスを使ってテキストノードを記述する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var element = new XElement("element",
+
      new XElement("child1", new XText("text1")),
+
      new XElement("child2", new XText("text2")),
+
      new XText("text3")
+
    );
+

          
+
    Console.WriteLine(element);
+
  }
+
}
+
}}
+
#column-end
+

          
+
#prompt(実行結果){{
+
<element>
+
  <child1>text1</child1>
+
  <child2>text2</child2>text3</element>
+
}}
+

          
+
このように、テキストノードを単に文字列で記述した場合とXTextクラスを用いて記述した場合では結果に違いはありません。 また、XTextクラスを用いてテキストノードを記述するとコードの記述量が増えるというデメリットはありますが、一方で単に文字列で記述した場合と比べるとそれがテキストノードであることを分かりやすくすることができるというメリットもあります。
+

          
+
#remarks
+
CDATAセクションを用いてテキストノードを記述したい場合は[[XCDataクラス>#XCData]]を用います。
+
#remarks-end
+

          
+

          
+

          
+
詳細は後述の[[#innertext_and_value]]で解説しますが、XElementでは数値など文字列以外の値を指定した場合はそれが自動的にテキストノードとして追加されます。 一方、XTextコンストラクタでは''文字列のみ''が指定できるため、数値などを指定することはできません。
+

          
+
#column
+
#code(cs,数値をテキストノードとして追加する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 数値をテキストノードとして追加する
+
    var element = new XElement("element",
+
      new XElement("value", 0),
+
      new XElement("value", 1.23)
+
    );
+

          
+
    Console.WriteLine(element);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<element>
+
  <value>0</value>
+
  <value>1.23</value>
+
</element>
+
}}
+
#column
+
#code(cs,XTextでは数値などからテキストノードを作成することはできない){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // XTextコンストラクタは文字列に限られるため、以下のように記述することはできない
+
    var element = new XElement("element",
+
      new XElement("value", new XText(0)),
+
      // error CS1503: 引数 1: 'int' から 'string' に変換できません
+
      new XElement("value", new XText(1.23))
+
      // error CS1503: 引数 1: 'double' から 'string' に変換できません
+
    );
+

          
+
    Console.WriteLine(element);
+
  }
+
}
+
}}
+
#column-end
+

          
+

          
+
**要素のテキスト・属性の値 [#innertext_and_value]
+
XElement・XAttributeコンストラクタの第二引数以降は&msdn(netfx,type,System.Object){Object型};になっていて、要素のテキスト・属性値として文字列だけでなく数値や&msdn(netfx,type,System.DateTimeOffset){DateTimeOffset型};、&msdn(netfx,type,System.Uri){Uriクラス};などの値を直接指定することができます。
+

          
+
コンストラクタで要素のテキスト・属性値として指定した値は、基本的にはToStringメソッドによって文字列化した場合と同じフォーマットで出力されますが、[[日時型(DateTime型・DateTimeOffset型)>programming/netfx/datetime/0_abstract]]を指定した場合はW3C-DTF形式(ISO8601形式)でフォーマットされます。 それ以外の書式で出力したい場合はToStringメソッドで目的の書式を指定して文字列化する必要があります。
+

          
+
#code(cs,要素のテキスト・属性値の指定){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("html",                  // XML文書のルート要素として<html>を作成
+
        new XElement("body",                // <html>要素の子要素として<body>を作成
+
          new XElement("a",                 // <body>要素の子要素として<a>を作成
+
            new XAttribute("href",          // <a>要素のhref属性の値にUriクラスのインスタンスを指定
+
                           new Uri("http://example.com/")), 
+
            "リンク"                        // <a>要素のテキストとして文字列"リンク"を指定
+
          ),
+
          new XElement("time",              // <body>要素の子要素として<time>を作成
+
            new XAttribute("datetime",      // <time>要素のdatetime属性の値にDateTimeOffsetの値を指定
+
                           DateTimeOffset.Now),
+
            DateTimeOffset.Now.ToString("D") // <time>要素のテキストとして、ToStringで文字列化したDateTimeOffsetの値を指定
+
          ),
+
          new XElement("span",              // <body>要素の子要素として<span>を作成
+
            0,                              // <span>要素のテキストとして数値・文字列を指定する
+
            "文字列",
+
            1.23)
+
        )
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<html>
+
  <body>
+
    <a href="http://example.com/">リンク</a>
+
    <time datetime="2016-02-22T12:34:56.789012+09:00">2016年2月22日</time>
+
    <span>0文字列1.23</span>
+
  </body>
+
</html>
+
}}
+

          
+
XElementコンストラクタで連続する複数のテキストを指定した場合は、上記のように一つの連結したテキストとして出力されます。 間に空白や区切り文字などが挟まれることはありません。
+

          
+
#remarks
+
DateTimeOffsetを文字列化する際の書式については[[programming/netfx/string_formatting/0_formatstrings#StandardDateAndTimeFormatStrings]]を参照してください。
+
#remarks-end
+

          
+

          
+

          
+
&msdn(netfx,type,System.TimeSpan){TimeSpan型};の値も日時と同様にISO8601形式の時間長(''duration'')として出力されます。 これ以外の書式で出力したい場合はToStringメソッドで目的の書式を指定して文字列化する必要があります。
+

          
+
#code(cs,TimeSpan型の値とフォーマット){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("e", TimeSpan.FromSeconds(1.0)), // 1秒
+
        new XElement("e", TimeSpan.FromMinutes(1.0)), // 1分
+
        new XElement("e", TimeSpan.FromHours(1.0)),   // 1時間
+
        new XElement("e", new TimeSpan(1, 2, 34, 56, 789)), // 1日と2時間34分56.789秒
+
        new XElement("e", TimeSpan.FromDays(0.9)),  // 0.9日
+
        new XElement("e", TimeSpan.FromDays(1.0)),  // 1.0日
+
        new XElement("e", TimeSpan.FromDays(1.1))   // 1.1日
+
      )
+
    );
+

          
+
    Console.WriteLine(doc.ToString());
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<root>
+
  <e>PT1S</e>
+
  <e>PT1M</e>
+
  <e>PT1H</e>
+
  <e>P1DT2H34M56.789S</e>
+
  <e>PT21H36M</e>
+
  <e>P1D</e>
+
  <e>P1DT2H24M</e>
+
</root>
+
}}
+

          
+
出力される時間長の書式は次のようになっています。
+
|*ISO8601形式の時間長における書式の記号と意味
+
|~記号|~意味|h
+
|``P``|以降の文字列が時間長で表される期間(''P''eriod)であることを表す|
+
|``&var{n};D``|日数(''D''ays)を表す|
+
|``T``|以降の文字列が時間長の時刻部分であることを表す&br;(``P&var{<日数>};T&var{<時間>};``)|
+
|``&var{n};H``|時間数(''H''ours)を表す|
+
|``&var{n};M``|分数(''M''inutes)を表す|
+
|``&var{n};S``&br;``&var{n};.&var{m};S``|秒数(''S''econds)を表す&br;端数(ミリ秒)がある場合は小数点数となる|
+

          
+
#relevantdocs(参考)
+
-[[https://en.wikipedia.org/wiki/ISO_8601#Durations]]
+

          
+
#relevantdocs-end
+

          
+
#remarks
+
TimeSpanを文字列化する際の書式については[[programming/netfx/string_formatting/0_formatstrings#StandardTimeSpanFormatStrings]]を参照してください。
+
#remarks-end
+

          
+

          
+
**子ノードの追加 (XElement.Add) [#XElement.Add]
+
&msdn(netfx,type,System.Xml.Linq.XDocument){XDocument};や&msdn(netfx,type,System.Xml.Linq.XElement){XElement};では、インスタンス作成時にコンストラクタで子ノードを格納するほかにも、インスタンス作成後に&msdn(netfx,member,System.Xml.Linq.XElement.Add){Addメソッド};などを使って子ノードを追加していくこともできます。
+

          
+
Addメソッドの引数もコンストラクタと同様に&msdn(netfx,type,System.Object){Object型};となっているため、[[#innertext_and_value]]と同じように要素に対してテキストノードや属性を追加する場合にもこのメソッドを使うことができます。
+

          
+
#code(cs,Addメソッドを使って要素に子ノードを追加する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // <p>要素
+
    var p = new XElement("p");
+

          
+
    p.Add("本文"); // <p>要素にテキストノード"本文"を追加する
+

          
+
    // <body>要素
+
    var body = new XElement("body");
+

          
+
    body.Add(p); // <p>要素を<body>要素の子ノードとして追加する
+

          
+
    // <head>要素
+
    var head = new XElement("head",
+
                            new XElement("title", "タイトル"));
+

          
+
    // <html>要素
+
    var html = new XElement("html");
+

          
+
    html.Add(head, body); // <head>要素と<body>要素を<html>要素の子ノードとして追加する
+

          
+
    // 属性lang="ja"を<html>要素に追加する
+
    html.Add(new XAttribute("lang", "ja"));
+

          
+
    // XML文書
+
    var doc = new XDocument();
+

          
+
    doc.Add(html); // <html>要素をドキュメントノード(ルートノード)として追加する
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<html lang="ja">
+
  <head>
+
    <title>タイトル</title>
+
  </head>
+
  <body>
+
    <p>本文</p>
+
  </body>
+
</html>
+
}}
+

          
+

          
+

          
+
Addメソッドのほかにも、ノードを追加したい位置に応じて次のメソッドを使うことができます。
+

          
+
|*ノードを追加するメソッド
+
|~メソッド|~動作|h
+
|&msdn(netfx,member,System.Xml.Linq.XContainer.Add){Add};(&var{node};)|&var{node};を子ノードの末尾に追加する|
+
|&msdn(netfx,member,System.Xml.Linq.XContainer.AddFirst){AddFirst};(&var{node};)|&var{node};を子ノードの先頭に追加する|
+
|&msdn(netfx,member,System.Xml.Linq.XContainer.AddBeforeSelf){AddBeforeSelf};(&var{node};)|&var{node};を自身の直前に追加する(兄ノードとして追加する)|
+
|&msdn(netfx,member,System.Xml.Linq.XContainer.AddAfterSelf){AddAfterSelf};(&var{node};)|&var{node};を自身の直後に追加する(弟ノードとして追加する)|
+

          
+
#remarks
+
これらのメソッドは&msdn(netfx,type,System.Xml.Linq.XContainer){XContainerクラス};によって提供され、このクラスを継承しているXDocumentやXElementでは共通してこのメソッドを使うことができます。
+
#remarks-end
+

          
+
これらのメソッドでノードが追加される位置を実際のコードを使って比較すると次のようになります。
+

          
+
#code(cs,ノードを追加するメソッドと追加される位置){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var self = new XElement("self",
+
                            new XElement("child"));
+
    var root = new XElement("root", self);
+

          
+
    // 追加前の状態を表示
+
    Console.WriteLine(root);
+
    Console.WriteLine();
+

          
+
    // AddXXXメソッドを使ってノードを追加
+
    self.Add(new XElement("last"));
+
    self.AddFirst(new XElement("first"));
+

          
+
    self.AddBeforeSelf(new XElement("before"));
+
    self.AddAfterSelf(new XElement("after"));
+

          
+
    // 追加後の状態を表示
+
    Console.WriteLine(root);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<root>
+
  <self>
+
    <child />
+
  </self>
+
</root>
+

          
+
<root>
+
  <before />
+
  <self>
+
    <first />
+
    <child />
+
    <last />
+
  </self>
+
  <after />
+
</root>
+
}}
+

          
+

          
+
**名前空間 (XNamespace) [#XNamespace]
+
この項での''名前空間''とは、プログラム要素としての名前空間(System.Xml.Linq名前空間など)ではなく、XML要素の名前空間(``xmlns``)のことです。 混同しないように注意してください。
+

          
+
名前空間付きの要素を作成したい場合は、&msdn(netfx,type,System.Xml.Linq.XNamespace){XNamespaceクラス};を使います。 XElementコンストラクタの第一引数に名前空間なしの要素名を指定するかわりに、次のように``&var{XNamespace}; + &var{要素名};``と指定することによって要素に名前空間を与えた上でXMLツリーに追加することができます。
+

          
+
|*要素(XElementインスタンス)の作成
+
|名前空間のない要素の作成|``new XElement(&var{要素名};)``|
+
|名前空間付きの要素の作成|``new XElement(&var{XNamespace}; + &var{要素名};)``|
+

          
+
#remarks
+
``&var{XNamespace}; + &var{要素名};``という式からは&msdn(netfx,type,System.Xml.Linq.XName){XNameクラス};のインスタンスが作成されます。 XNameクラスについて詳しくは[[#XName]]で解説します。
+
#remarks-end
+

          
+
XNamespaceのインスタンスは、名前空間名の文字列を型変換することで作成します。 コンストラクタを使った作成はできない点に注意してください。
+

          
+
#code(cs,XNamespaceを使って名前空間付きの要素を作成する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 名前空間
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+
    var nsSy = (XNamespace)"http://purl.org/rss/1.0/modules/syndication/";
+

          
+
    var doc = new XDocument(
+
      // 名前空間付きの要素
+
      new XElement(nsAtom + "feed",
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "updated", DateTimeOffset.Now),
+
        new XElement(nsSy + "updatePeriod", "daily")
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(出力結果){{
+
<feed xmlns="http://www.w3.org/2005/Atom">
+
  <title>更新履歴 (Atom 1.0)</title>
+
  <updated>2016-02-22T12:34:56.789012+09:00</updated>
+
  <updatePeriod xmlns="http://purl.org/rss/1.0/modules/syndication/">daily</updatePeriod>
+
</feed>
+
}}
+

          
+
上記のように、要素に与えた各名前空間はプレフィックスなしのデフォルト名前空間として出力されます。 同一スコープ内にある同一名前空間の要素は自動的に弁別されるため、すべての要素に名前空間を指定しても、そのすべてに``xmlns``属性が付与されることはありません。
+

          
+

          
+

          
+
名前空間付きの要素を作成する場合、XElementコンストラクタの第一引数に"``{&var{名前空間};}&var{要素名};``"のような''展開された''名前を指定することもできます。 ただし、このような指定は名前空間と要素名の解析処理が必要となり非効率であるため、推奨される方法ではありません。 特別な理由がない限りはXNamespaceクラスを使用するようにしてください。
+

          
+
#code(cs,展開された名前を使って名前空間付きの要素を作成する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // '展開された'名前を使って名前空間付きの要素を作成する
+
      new XElement("{http://www.w3.org/2005/Atom}feed",
+
        new XElement("{http://www.w3.org/2005/Atom}title", "更新履歴 (Atom 1.0)"),
+
        new XElement("{http://www.w3.org/2005/Atom}updated", DateTimeOffset.Now),
+
        new XElement("{http://purl.org/rss/1.0/modules/syndication/}updatePeriod", "daily")
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<feed xmlns="http://www.w3.org/2005/Atom">
+
  <title>更新履歴 (Atom 1.0)</title>
+
  <updated>2016-02-22T12:34:56.789012+09:00</updated>
+
  <updatePeriod xmlns="http://purl.org/rss/1.0/modules/syndication/">daily</updatePeriod>
+
</feed>
+
}}
+

          
+
***名前空間のプレフィックス
+
名前空間を指定した要素を、名前空間プレフィックス(接頭辞)付きの要素名(''qualified name'')で出力したい場合は、XAttributeを使って要素に``xmlns``属性を付与して名前空間とプレフィックスの宣言をします。 例えば``new XAttribute(XNamespace.Xmlns + "ex", "http&#x3A;//example.com/")``とすれば、```xmlns:ex="http&#x3A;//example.com/"```という``xmlns``属性を表すXAttributeインスタンスが作成されます。
+

          
+
|*名前空間宣言となるXAttributeインスタンスの作成
+
|~名前空間宣言となるxmlns属性|~名前空間宣言を作成するためのXAttributeインスタンス|h
+
|```xmlns:ex="http&#x3A;//example.com/"```|``new XAttribute(XNamespace.Xmlns + "ex", "http&#x3A;//example.com/")``|
+
|```xmlns:xsl="http&#x3A;//www.w3.org/1999/XSL/Transform"```|``new XAttribute(XNamespace.Xmlns + "xsl", "http&#x3A;//www.w3.org/1999/XSL/Transform")``|
+
|```xmlns:atom="http&#x3A;//www.w3.org/2005/Atom"```|``new XAttribute(XNamespace.Xmlns + "atom", "http&#x3A;//www.w3.org/2005/Atom")``|
+

          
+
このような属性をもつ要素では、その要素と、要素内にある同一名前空間の要素すべてに対して自動的にプレフィックスが付与されます。
+

          
+
#code(cs,XAttributeクラスを用いて名前空間プレフィックス付きの要素を作成する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+
    var nsSy = (XNamespace)"http://purl.org/rss/1.0/modules/syndication/";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsAtom + "feed",
+
        // Atomの名前空間に属する要素にはプレフィックス"atom"を付ける
+
        new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
        // Syndicationの名前空間に属する要素にはプレフィックス"sy"を付ける
+
        new XAttribute(XNamespace.Xmlns + "sy", nsSy.NamespaceName),
+

          
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "updated", DateTimeOffset.Now),
+
        new XElement(nsSy + "updatePeriod", "daily")
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(出力結果){{
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <atom:updated>2016-02-22T12:34:56.789012+09:00</atom:updated>
+
  <sy:updatePeriod>daily</sy:updatePeriod>
+
</atom:feed>
+
}}
+

          
+
上記の例にあるように、名前空間名は&msdn(netfx,member,System.Xml.Linq.XNamespace.NamespaceName){XNamespace.NamespaceNameプロパティ};より参照することができるため、何度も同じ名前空間名を文字列で記述する必要がなくなります。
+

          
+

          
+

          
+
プレフィックス付きの属性名を作成する場合も要素と同様に行うことができます。
+

          
+
#code(cs,XAttributeクラスを用いて名前空間プレフィックス付きの属性を作成する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsRss = (XNamespace)"http://purl.org/rss/1.0/";
+
    var nsRdf = (XNamespace)"http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsRdf + "RDF",
+
        // RSS1.0の名前空間に属する要素・属性にはプレフィックス"rss"を付ける
+
        new XAttribute(XNamespace.Xmlns + "rss", nsRss.NamespaceName),
+
        // RDFの名前空間に属する要素・属性にはプレフィックス"rdf"を付ける
+
        new XAttribute(XNamespace.Xmlns + "rdf", nsRdf.NamespaceName),
+

          
+
        new XElement(nsRss + "channel",
+
          new XAttribute(nsRdf + "about", "http://example.com/rss10.rdf"),
+
          new XElement(nsRss + "title", "更新履歴 (RSS 1.0)"),
+
          new XElement(nsRss + "items",
+
            new XElement(nsRdf + "Seq",
+
              new XElement(nsRdf + "li", new XAttribute(nsRdf + "resource", "tag:example.com,2016-02-22:update1")),
+
              new XElement(nsRdf + "li", new XAttribute(nsRdf + "resource", "tag:example.com,2016-02-22:update2")),
+
              new XElement(nsRdf + "li", new XAttribute(nsRdf + "resource", "tag:example.com,2016-02-22:update3"))
+
            )
+
          )
+
        )
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<rdf:RDF xmlns:rss="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+
  <rss:channel rdf:about="http://example.com/rss10.rdf">
+
    <rss:title>更新履歴 (RSS 1.0)</rss:title>
+
    <rss:items>
+
      <rdf:Seq>
+
        <rdf:li rdf:resource="tag:example.com,2016-02-22:update1" />
+
        <rdf:li rdf:resource="tag:example.com,2016-02-22:update2" />
+
        <rdf:li rdf:resource="tag:example.com,2016-02-22:update3" />
+
      </rdf:Seq>
+
    </rss:items>
+
  </rss:channel>
+
</rdf:RDF>
+
}}
+

          
+

          
+
***プレフィックスとデフォルト名前空間の併用
+
特定の名前空間にプレフィックスを付けたくない場合、必要な要素・属性だけにプレフィックスを付けたい場合は、デフォルト名前空間と併用することができます。 例えばルート要素と同じ名前空間の要素にはプレフィックスを付与したくないといった場合には、プレフィックスの宣言をしないことでデフォルト名前空間として出力させることができます。
+

          
+
#code(cs,名前空間プレフィックスとデフォルト名前空間を併用して要素を出力する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+
    var nsSy = (XNamespace)"http://purl.org/rss/1.0/modules/syndication/";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsAtom + "feed",
+
        // Atomの名前空間に属する要素にはプレフィックスを付けない
+
        // new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
        // Syndicationの名前空間に属する要素にはプレフィックスを付ける
+
        new XAttribute(XNamespace.Xmlns + "sy", nsSy.NamespaceName),
+

          
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "updated", DateTimeOffset.Now),
+
        new XElement(nsSy + "updatePeriod", "daily")
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<feed xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns="http://www.w3.org/2005/Atom">
+
  <title>更新履歴 (Atom 1.0)</title>
+
  <updated>2016-02-22T12:34:56.789012+09:00</updated>
+
  <sy:updatePeriod>daily</sy:updatePeriod>
+
</feed>
+
}}
+

          
+
***名前 (XName) [#XName]
+
&msdn(netfx,type,System.Xml.Linq.XName){XNameクラス};は要素や属性の''名前''を扱うクラスで、名前空間名とローカル名(''名前''のうち、名前空間によって修飾される部分)をセットで保持します。 XElementやXAttributeのコンストラクタの第一引数で指定した要素・属性の名前はXNameに変換され、各クラスで保持されます。 名前空間のない要素名・属性名の場合もXNameとして保持されます。
+

          
+
次の例のように、要素名・属性名となるXNameのインスタンスを事前に作成しておき、要素・属性を作成する際にXElementとXAttributeに与える名前として直接XNameを指定することができます。 特に、名前空間を多く扱うXML文書では``&var{XNamespace}; + "&var{要素名・属性名};"``を記述することが多くなりますが、そのような場合にXNameを使うと記述を簡略化できます。
+

          
+
#column
+
#code(cs,XNameを用いて名前空間で修飾された要素を作成する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+
    // 名前空間で修飾された要素名となるXNameを作成
+
    XName elemFeed = nsAtom + "feed";
+
    XName elemTitle = nsAtom + "title";
+

          
+
    var doc = new XDocument(
+
      // XNameを使って名前空間で修飾された名前を持つ要素を作成する
+
      new XElement(elemFeed,
+
        new XElement(elemTitle, "更新履歴 (Atom 1.0)")
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+
#column
+
#code(cs,XNameを用いずに名前空間で修飾された要素を作成する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+

          
+

          
+

          
+

          
+
    var doc = new XDocument(
+
      // XNameを使わずに名前空間で修飾された名前を持つ要素を作成する
+
      new XElement(nsAtom + "feed",
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)")
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+
#column-end
+

          
+
比較のためXNameを用いた場合とそうでない場合を併記していますが、上記のいずれも同じXMLツリーを生成します。
+

          
+
#prompt(実行結果){{
+
<feed xmlns="http://www.w3.org/2005/Atom">
+
  <title>更新履歴 (Atom 1.0)</title>
+
</feed>
+
}}
+

          
+
このように``&var{XNamespace}; + "&var{ローカル名};"``とすれば名前空間付きの名前を表すXNameが作成されます。 名前空間なしの名前の場合は、ローカル名の文字列を直接XNameにキャストするか、名前空間が無いことを表す&msdn(netfx,member,System.Xml.Linq.XNamespace.None){XNamespace.Noneプロパティ};とローカル名を連結して作成します。
+

          
+
|*XNameインスタンスの作成
+
|>|~XNameを作成する構文|~作成されるXNameの展開名|h
+
|~名前空間付き|``(XNamespace)"http&#x3A;//example.com/ns" + "localname"``|```{http&#x3A;//example.com/ns}localname```|
+
|~名前空間なし|``(XName)"localname"``|```localname```|
+
|~|``XNamespace.None + "localname"``|```localname```|
+

          
+

          
+

          
+

          
+

          
+
要素名・属性名はそれぞれ&msdn(netfx,member,System.Xml.Linq.XElement.Name){XElement.Nameプロパティ};と&msdn(netfx,member,System.Xml.Linq.XAttribute.Name){XAttribute.Nameプロパティ};にXNameの形で格納されます。 &msdn(netfx,member,System.Xml.Linq.XName.Namespace){XName.Namespaceプロパティ};を参照すれば名前空間名、&msdn(netfx,member,System.Xml.Linq.XName.LocalName){XName.LocalNameプロパティ};を参照すればローカル名を取得することができます。 &msdn(netfx,member,System.Xml.Linq.XName.ToString){XName.ToStringメソッド};などによって文字列化した場合は、名前空間が''展開された''名前を取得することができます。
+

          
+
#code(cs,XElement.Nameプロパティを参照して要素の名前・名前空間名・ローカル名を取得する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+
    var feed = new XElement(nsAtom + "feed"); // 名前空間付きの要素
+

          
+
    // 要素の名前を取得して表示
+
    Console.WriteLine("Name = {0}", feed.Name);                 // 展開名を取得して表示
+
    Console.WriteLine("Namespace = {0}", feed.Name.Namespace);  // 名前空間名を取得して表示
+
    Console.WriteLine("LocalName = {0}", feed.Name.LocalName);  // ローカル名を取得して表示
+

          
+
    Console.WriteLine("------------");
+

          
+
    var rss = new XElement(XNamespace.None + "rss"); // 名前空間のない要素
+

          
+
    Console.WriteLine("Name = {0}", rss.Name);
+
    Console.WriteLine("Namespace = {0}", rss.Name.Namespace);
+
    Console.WriteLine("LocalName = {0}", rss.Name.LocalName);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
Name = {http://www.w3.org/2005/Atom}feed
+
Namespace = http://www.w3.org/2005/Atom
+
LocalName = feed
+
------------
+
Name = rss
+
Namespace = 
+
LocalName = rss
+
}}
+

          
+

          
+

          
+
XNameクラスではインスタンスがキャッシュされ、同一名前空間かつ同一ローカル名の名前を持つXNameを作成すると常に同一のインスタンスが返されます。 例えば次のように要素ごとに名前を指定してXNameを作成した場合でも、あらかじめ作成したXNameを用いた場合でも、それらはすべて同一のインスタンスが用いられます。
+

          
+
#code(cs,type=benchmark,XNameインスタンスのキャッシュ){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 要素毎にXNameを作成した場合
+
    var e1 = new XElement((XNamespace)"http://example.com/ns" + "localname");
+
    var e2 = new XElement((XNamespace)"http://example.com/ns" + "localname");
+

          
+
    Console.WriteLine("e1.Name == e2.Name : {0}", Object.ReferenceEquals(e1.Name, e2.Name));
+

          
+
    // 要素でXNameを共用した使用した場合
+
    var name = (XNamespace)"http://example.com/ns" + "localname";
+

          
+
    var e3 = new XElement(name);
+
    var e4 = new XElement(name);
+

          
+
    Console.WriteLine("e3.Name == e4.Name : {0}", Object.ReferenceEquals(e3.Name, e4.Name));
+

          
+
    Console.WriteLine("e1.Name == e3.Name : {0}", Object.ReferenceEquals(e1.Name, e3.Name));
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
e1.Name == e2.Name : True
+
e3.Name == e4.Name : True
+
e1.Name == e3.Name : True
+
}}
+

          
+

          
+

          
+
*特殊なノード
+
**XML宣言 (XDeclaration) [#XDeclaration]
+
XML宣言を明示的に設定したい場合は、&msdn(netfx,type,System.Xml.Linq.XDeclaration){XDeclarationクラス};を使って指定します。
+

          
+
#code(cs,XDeclarationクラスを使ってXML宣言を設定する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // XML宣言
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      new XElement("rss",
+
        new XAttribute("version", "2.0"),
+
        new XElement("channel",
+
          new XElement("title", "更新履歴 (RSS 2.0)")
+
        )
+
      )
+
    );
+

          
+
    // ファイルtest.xmlに保存
+
    doc.Save("test.xml");
+

          
+
    // 以下の呼び出しではXML宣言は出力されない
+
    //Console.WriteLine(doc);
+
    //Console.WriteLine(doc.ToString());
+
  }
+
}
+
}}
+

          
+
#code(xml,type=output,test.xmlに出力される内容){{
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
<rss version="2.0">
+
  <channel>
+
    <title>更新履歴 (RSS 2.0)</title>
+
  </channel>
+
</rss>
+
}}
+

          
+
Saveメソッドなどによって出力する場合、XDeclarationが無くてもXML宣言が出力されます。 一方、ToStringメソッドによって文字列化した場合は、XDeclarationの有無に関わらずXML宣言は出力されません。
+

          
+
Saveメソッドによる出力時オプションについては[[#XDocument.Save]]、またXML宣言と出力時の文字コードの扱いなどについては[[programming/netfx/xml/1_xmlwritersettings#XmlWriterSettings.Encoding]]を参照してください。
+

          
+

          
+

          
+
XML宣言は&msdn(netfx,member,System.Xml.Linq.XDocument.Declaration){XDocument.Declarationプロパティ};を使うことによっても取得・設定することができます。
+

          
+
#code(cs,XDocument.Declarationプロパティを使ってXML宣言を設定する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("rss",
+
        new XAttribute("version", "2.0"),
+
        new XElement("channel",
+
          new XElement("title", "更新履歴 (RSS 2.0)")
+
        )
+
      )
+
    );
+

          
+
    // プロパティを使ってXML宣言を設定する
+
    doc.Declaration = new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes");
+

          
+
    // ファイルtest.xmlに保存
+
    doc.Save("test.xml");
+
  }
+
}
+
}}
+

          
+
#code(xml,type=output,test.xmlに出力される内容){{
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
<rss version="2.0">
+
  <channel>
+
    <title>更新履歴 (RSS 2.0)</title>
+
  </channel>
+
</rss>
+
}}
+

          
+

          
+

          
+
XDocumentに複数のXML宣言を持たせることはできません。 XDocumentに複数のXDeclarationを持たせようとした場合、&msdn(netfx,type,System.ArgumentException){ArgumentException};がスローされます。
+

          
+
#code(cs,複数のXML宣言を持たせることはできない){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // 1つ目のXDeclaration
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      // 2つ目のXDeclaration
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes")
+
    );
+

          
+
    doc.Save("test.xml");
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
ハンドルされていない例外: System.ArgumentException: 空白以外の文字をコンテンツに追加できません。
+
   場所 System.Xml.Linq.XDocument.ValidateString(String s)
+
   場所 System.Xml.Linq.XContainer.AddStringSkipNotify(String s)
+
   場所 System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
+
   場所 Sample.Main()
+
}}
+

          
+

          
+
**DOCTYPE宣言 (XDocumentType) [#XDocumentType]
+
DOCTYPE宣言(ドキュメントタイプ)を記述する場合は、&msdn(netfx,type,System.Xml.Linq.XDocumentType){XDocumentTypeクラス};を使います。
+

          
+
#code(cs,XDocumentTypeクラスを用いてDOCTYPE宣言を設定する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // DOCTYPE宣言
+
      new XDocumentType("html", null, null, null),
+
      new XElement("html",
+
        new XElement("head",
+
          new XElement("title", "タイトル")
+
        ),
+
        new XElement("body",
+
          new XElement("p", "段落")
+
        )
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<!DOCTYPE html >
+
<html>
+
  <head>
+
    <title>タイトル</title>
+
  </head>
+
  <body>
+
    <p>段落</p>
+
  </body>
+
</html>
+
}}
+

          
+
[[XML宣言>#XDeclaration]]と同様、&msdn(netfx,member,System.Xml.Linq.XDocument.DocumentType){XDocument.DocumentTypeプロパティ};を使ってDOCTYPE宣言を参照することはできますが、このプロパティは読み取り専用プロパティであるため設定することはできません。
+

          
+
#code(cs,XDocument.DocumentTypeプロパティを使ってDOCTYPE宣言を設定することはできない){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("html",
+
        new XElement("head",
+
          new XElement("title", "タイトル")
+
        ),
+
        new XElement("body",
+
          new XElement("p", "段落")
+
        )
+
      )
+
    );
+

          
+
    // プロパティを使ってDOCTYPE宣言を設定することはできない
+
    doc.DocumentType = new XDocumentType("html", null, null, null);
+
    // error CS0200: プロパティまたはインデクサー 'System.Xml.Linq.XDocument.DocumentType' は読み取り専用なので、割り当てることはできません
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+

          
+

          
+
XDocumentに複数のDOCTYPE宣言を持たせることはできません。 XDocumentに複数のXDocumentTypeを持たせようとした場合、&msdn(netfx,type,System.InvalidOperationException){InvalidOperationException};がスローされます。
+

          
+
#code(cs,XDocumentに複数のDOCTYPE宣言を持たせることはできない){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // 1つ目のXDocumentType
+
      new XDocumentType("html", null, null, null),
+
      // 2つ目のXDocumentType
+
      new XDocumentType("html", null, null, null)
+
    );
+

          
+
    doc.Save("test.xml");
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
ハンドルされていない例外: System.InvalidOperationException: この操作を実行すると構造の正しくないドキュメントが作成されます。
+
   場所 System.Xml.Linq.XDocument.ValidateDocument(XNode previous, XmlNodeType allowBefore, XmlNodeType allowAfter)
+
   場所 System.Xml.Linq.XContainer.AddNodeSkipNotify(XNode n)
+
   場所 System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
+
   場所 Sample.Main()
+
}}
+

          
+

          
+
**XML処理命令 (XProcessingInstruction) [#XProcessingInstruction]
+
XML処理命令(''Processing Instruction'')を記述する場合は、&msdn(netfx,type,System.Xml.Linq.XProcessingInstruction){XProcessingInstructionクラス};を使います。
+

          
+
#code(cs,XProcessingInstructionクラスを使ってXML処理命令を記述する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // XML処理命令
+
      new XProcessingInstruction("xml-stylesheet", "type=\"text/css\" href=\"feed.css\""),
+
      new XElement("rss",
+
        new XAttribute("version", "2.0"),
+
        new XElement("channel",
+
          new XElement("title", "更新履歴 (RSS 2.0)")
+
        )
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<?xml-stylesheet type="text/css" href="feed.css"?>
+
<rss version="2.0">
+
  <channel>
+
    <title>更新履歴 (RSS 2.0)</title>
+
  </channel>
+
</rss>
+
}}
+

          
+

          
+
**コメントノード (XComment) [#XComment]
+
XMLツリー内にコメントを記述する場合は、&msdn(netfx,type,System.Xml.Linq.XComment){XCommentクラス};を使います。 XElementクラス等とは異なり、&msdn(netfx,member,System.Xml.Linq.XComment..ctor){XCommentコンストラクタ};の引数に指定できるのは常にコメントとなる単一の文字列だけです。 複数の文字列や数値を指定したりすることはできないため、あらかじめ&msdn(netfx,member,System.String.Format){String.Formatメソッド};や&msdn(netfx,member,System.String.Join){String.Joinメソッド};などによってフォーマット・結合しておく必要があります。
+

          
+
コメントノードはルート要素の前後を含む任意の位置に追加することができます。
+

          
+
#code(cs,XCommentクラスを使ってXMLツリー内にコメントを挿入する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XComment("コメント"),
+
      new XElement("root", new XComment("コメント")),
+
      new XComment("コメント")
+
      // XCommentではXElementのように複数の引数を与えることはできない
+
      //new XComment("コメント", "コメント", "コメント")
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<!--コメント-->
+
<root>
+
  <!--コメント-->
+
</root>
+
<!--コメント-->
+
}}
+

          
+

          
+

          
+
XCommentクラスでは、"``<!--``"や"``-->``"などのコメント開始・終了のマークを含む文字列もコメントとして指定することができます。 この場合、&msdn(netfx,type,System.ArgumentException){ArgumentException};などの例外はスローされず、ハイフン"``-``"が2つ以上連続している個所に対して自動的に空白が挿入された上でコメントノードが作成されます。
+

          
+
#code(cs,コメント内にコメント開始・終了のマークが含まれている場合){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XComment("XXX<!--"),
+
      new XComment("-->XXX"),
+
      new XComment("--XXX"),
+
      new XComment("XXX--"),
+
      new XComment("--XXX----XXX--")
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<!--XXX<!- - -->
+
<!--- ->XXX-->
+
<!--- -XXX-->
+
<!--XXX- - -->
+
<!--- -XXX- - - -XXX- - -->
+
}}
+

          
+
#remarks
+
なお、&msdn(netfx,member,System.Xml.XmlDocument.CreateComment){System.Xml.XmlDocument.CreateCommentメソッド};では、このようなコメントノードを追加しようとした場合には&msdn(netfx,type,System.ArgumentException){ArgumentException};がスローされます。
+

          
+
#code(cs,System.Xml.XmlDocumentクラスでコメント開始・終了のマークを含むコメントノードを追加しようとした場合){{
+
using System;
+
using System.Xml;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XmlDocument();
+

          
+
    // 以下のいずれの呼び出しもArgumentExceptionをスローする
+
    doc.AppendChild(doc.CreateComment("XXX<!--"));
+
    doc.AppendChild(doc.CreateComment("-->XXX"));
+
    doc.AppendChild(doc.CreateComment("--XXX"));
+
    doc.AppendChild(doc.CreateComment("XXX--"));
+
    doc.AppendChild(doc.CreateComment("--XXX----XXX--"));
+
  }
+
}
+
}}
+

          
+
XmlDocumentとXDocumentを並行して扱う場合や実装の書き換えを行う際には動作が異なる点に注意してください。
+
#remarks-end
+

          
+
**CDATAセクション (XCData) [#XCData]
+
テキストノード内にCDATAセクションを記述する場合は、&msdn(netfx,type,System.Xml.Linq.XCData){XCDataクラス};を使います。 CDATAセクションを用いると、テキストノード内で``<``、``>``、``"``といった記号を文字参照形式ではなくそのまま記述することができます。 [[XCommentコンストラクタ>#XComment]]と同様、&msdn(netfx,member,System.Xml.Linq.XCData..ctor){XCDataコンストラクタ};も引数に指定できるのは常にCDATAセクションとなる単一の文字列だけです。 複数の文字列や数値を指定したりすることはできないため、あらかじめ結合しておく必要があります。
+

          
+
#code(cs,XCDataクラスを使ってテキストノード内にCDATAセクションを記述する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("text",
+
          // CDATAセクションを用いてC#コードを記述する
+
          new XCData("var list = new List<string>() {\"foo\", \"bar\", \"baz\"};")
+
        ),
+
        new XElement("text",
+
          // CDATAセクションを用いてXMLコードを記述する
+
          new XCData(@"<?xml version=""1.0"" encoding=""utf-8"" standalone=""yes""?>
+
  <rss version=""2.0"">
+
    <channel>
+
      <title>更新履歴 (RSS 2.0)</title>
+
    </channel>
+
  </rss>
+
  ")
+
        )
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(出力結果){{
+
<root>
+
  <text><![CDATA[var list = new List<string>() {"foo", "bar", "baz"};]]></text>
+
  <text><![CDATA[<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
  <rss version="2.0">
+
    <channel>
+
      <title>更新履歴 (RSS 2.0)</title>
+
    </channel>
+
  </rss>
+
  ]]></text>
+
</root>
+
}}
+

          
+

          
+

          
+
一つの要素内に通常のテキストとCDATAセクションを混在させることもできます。
+

          
+
#code(cs,テキストとCDATAセクションを混在させる){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        "foo",
+
        new XCData("bar"),
+
        "baz"
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(出力結果){{
+
<root>foo<![CDATA[bar]]>baz</root>
+
}}
+

          
+
#remarks
+
このようにして出力されたXMLが読み込まれる際には、テキストノードとCDATAセクション内のテキストが連結された状態で読み込まれます。 つまり、上記のXML文書における``<root>``要素はテキスト``"foobarbaz"``を持っている状態となります。
+
#remarks-end
+

          
+

          
+

          
+
XCDataクラスでは、CDATAセクションの開始・終了のマーク("``<![CDATA[``"および"``]]>``")を含む文字列もCDATAセクションの文字列として指定することができます。 この場合、&msdn(netfx,type,System.ArgumentException){ArgumentException};などの例外はスローされません。 また、終了マーク"``]]>``"に関しては、"``]]``"と"``>``"がそれぞれ個別のCDATAセクションに分割された状態で作成されます。
+

          
+
#code(cs,XCDataクラスを用いてCDATAセクションの開始・終了マークを含む文字列を出力する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("text", new XCData("<![CDATA[")), // CDATAセクションの開始マーク
+
        new XElement("text", new XCData("]]>")) // CDATAセクションの終了マーク
+
      )
+
    );
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<root>
+
  <text><![CDATA[<![CDATA[]]></text>
+
  <text><![CDATA[]]]]><![CDATA[>]]></text>
+
</root>
+
}}
+

          
+

          
+

          
+
*XMLフラグメント
+
**XMLフラグメントの構築
+
次のようにXElementだけを用いればXMLフラグメント(不完全なXML文書の断片)を構築することもできます。
+

          
+
#code(cs,XMLフラグメントを構築する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var fragment = new XElement("body",
+
      new XComment("本文"),
+
      new XElement("p", "段落"),
+
      new XElement("p", "段落")
+
    );
+

          
+
    Console.WriteLine(fragment);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<body>
+
  <!--本文-->
+
  <p>段落</p>
+
  <p>段落</p>
+
</body>
+
}}
+

          
+

          
+

          
+
XElementクラスもXDocumentクラス同様の&msdn(netfx,member,System.Xml.Linq.XElement.Save){Saveメソッド};を持っているため、XMLフラグメントをファイルなどに保存することができます。 この際、デフォルトではXML宣言を含んだ状態で保存されます。
+

          
+
#code(cs,XElement.Saveメソッドを使ってXMLフラグメントをファイルに保存する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var fragment = new XElement("body",
+
      new XComment("本文"),
+
      new XElement("p", "段落"),
+
      new XElement("p", "段落")
+
    );
+

          
+
    fragment.Save("test.xml");
+
  }
+
}
+
}}
+

          
+
#code(xml,type=output,test.xmlに出力される内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<body>
+
  <!--本文-->
+
  <p>段落</p>
+
  <p>段落</p>
+
</body>
+
}}
+

          
+
#remarks
+
XML宣言を含まずに保存したい場合はXmlWriterを使います。 詳しくは[[programming/netfx/xml/1_xmlwritersettings#XmlWriterSettings.OmitXmlDeclaration]]を参照してください。
+
#remarks-end
+

          
+
**XMLフラグメントのインポート (XElement.Parse) [#XElement.Parse]
+
&msdn(netfx,member,System.Xml.Linq.XElement.Parse){XElement.Parseメソッド};を用いると、文字列で記述されたXMLフラグメントを読み込んでXElementをルートとするXMLツリーを構築することができます。
+

          
+
#code(cs,XElement.Parseメソッドを使ってXMLフラグメントをXML文書にインポートする){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root")
+
    );
+

          
+
    // 文字列からXMLフラグメントを生成する
+
    var fragment = XElement.Parse(@"<fragment>
+
  <foo>foo</foo>
+
  <bar>bar</bar>
+
</fragment>");
+

          
+
    // XMLフラグメントのツリーをルート要素に追加する
+
    doc.Root.Add(fragment);
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<root>
+
  <fragment>
+
    <foo>foo</foo>
+
    <bar>bar</bar>
+
  </fragment>
+
</root>
+
}}
+

          
+
#remarks
+
XDocumentクラスにも&msdn(netfx,member,System.Xml.Linq.XDocument.Parse){XDocument.Parseメソッド};が用意されているため、XDocumentクラスでも文字列からXML文書を構築することができます。
+
#remarks-end
+

          
+

          
+

          
+
XElement.Parseメソッドで読み込めるのは一つの要素をルートとするXMLフラグメントのみです。 ルートに複数の要素があるようなXMLフラグメントを読み込むことはできません。
+

          
+
#code(cs,XElement.Parseメソッドではルートに複数の要素があるXMLフラグメントを読み込むことはできない){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root")
+
    );
+

          
+
    // ルートに2つの要素が含まれるXMLフラグメントを読み込もうとする
+
    // (実際にはSystem.Xml.XmlExceptionがスローされる)
+
    var fragment = XElement.Parse(@"<foo>foo</foo>
+
<bar>bar</bar>");
+

          
+
    doc.Root.Add(fragment);
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
ハンドルされていない例外: System.Xml.XmlException: ルート要素が複数あります。 行 2、位置 2。
+
   場所 System.Xml.XmlTextReaderImpl.Throw(Exception e)
+
   場所 System.Xml.XmlTextReaderImpl.ParseDocumentContent()
+
   場所 System.Xml.Linq.XElement.Load(XmlReader reader, LoadOptions options)
+
   場所 System.Xml.Linq.XElement.Parse(String text, LoadOptions options)
+
   場所 Sample.Main()
+
}}
+

          
+
ルートに複数の要素を含むXMLフラグメントを読み込みたい場合は、以下のように仮のルート要素で包んだ上で読み込むようにします。 その後、&msdn(netfx,member,System.Xml.Linq.XElement.Elements){XElement.Elements()メソッド};を使って読み込んだルート要素内に含まれる子要素だけを取り出します。
+

          
+
#code(cs,XElement.Parseメソッドでルートに複数の要素があるXMLフラグメントを読み込む){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root")
+
    );
+

          
+
    // ルートに2つの要素が含まれるXMLフラグメントを読み込みたい
+
    string fragment = @"<foo>foo</foo>
+
<bar>bar</bar>";
+

          
+
    // XMLフラグメントを仮のルート要素<wrapper>で包んだ上で読み込み、
+
    // Elementsメソッドを使って<wrapper>の子要素だけを取り出す
+
    var elements = XElement.Parse("<wrapper>" + fragment + "</wrapper>").Elements();
+

          
+
    // 取り出した要素をルート要素に追加する
+
    doc.Root.Add(elements);
+

          
+
    Console.WriteLine(doc);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<root>
+
  <foo>foo</foo>
+
  <bar>bar</bar>
+
</root>
+
}}
+

          
+

          
+

          
+
名前空間を持つXMLフラグメントをインポートしてXML文書を組み立てる場合、各XMLフラグメントで宣言している名前空間が重複する場合があります。 例えば次のようなコードでXML文書を構築した場合、同じ名前空間の宣言が複数箇所に存在するようになります。
+

          
+
#code(cs,XDocument.Parseメソッド・XElement.Parseメソッドを使ってcsprojファイルを構築する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // csprojファイルのテンプレートとなるXDocument
+
    var doc = XDocument.Parse(@"<?xml version=""1.0"" encoding=""utf-8""?>
+
<Project DefaultTargets=""Build"" ToolsVersion=""4.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+
  <PropertyGroup>
+
    <AssemblyName>Sample</AssemblyName>
+
    <OutputType>exe</OutputType>
+
    <OutputPath>.\bin\</OutputPath>
+
    <IntermediateOutputPath>.\obj\</IntermediateOutputPath>
+
  </PropertyGroup>
+
  <Import Project=""$(MSBuildBinPath)\Microsoft.CSharp.targets"" />
+
</Project>
+
");
+

          
+
    // コンパイルするファイルを定義するItemGroupのXMLフラグメント
+
    var elementItemGroupCompile = XElement.Parse(@"
+
<ItemGroup xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+
  <Compile Include=""Properties\AssemblyInfo.cs"" />
+
  <Compile Include=""Main.cs"" />
+
  <Compile Include=""Class1.cs"" />
+
  <Compile Include=""Class2.cs"" />
+
  <Compile Include=""Class3.cs"" />
+
</ItemGroup>
+
");
+

          
+
    // 参照するアセンブリを定義するItemGroupのXMLフラグメント
+
    var elementItemGroupReference = XElement.Parse(@"
+
<ItemGroup xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
+
  <Reference Include=""System"" />
+
  <Reference Include=""System.Core"" />
+
</ItemGroup>
+
");
+

          
+
    // 読み込んだXMLフラグメントをXML文書に追加する
+
    doc.Root.Add(elementItemGroupCompile);
+
    doc.Root.Add(elementItemGroupReference);
+

          
+
    // 構築したXML文書をファイルに保存する
+
    doc.Save("test.csproj");
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,test.csprojの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
  <PropertyGroup>
+
    <AssemblyName>Sample</AssemblyName>
+
    <OutputType>exe</OutputType>
+
    <OutputPath>.\bin\</OutputPath>
+
    <IntermediateOutputPath>.\obj\</IntermediateOutputPath>
+
  </PropertyGroup>
+
  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+
  <ItemGroup xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
    <Compile Include="Properties\AssemblyInfo.cs" />
+
    <Compile Include="Main.cs" />
+
    <Compile Include="Class1.cs" />
+
    <Compile Include="Class2.cs" />
+
    <Compile Include="Class3.cs" />
+
  </ItemGroup>
+
  <ItemGroup xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
    <Reference Include="System" />
+
    <Reference Include="System.Core" />
+
  </ItemGroup>
+
</Project>
+
}}
+

          
+
このような場合はSaveメソッドの引数で&msdn(netfx,member,System.Xml.Linq.SaveOptions.OmitDuplicateNamespaces){SaveOptions.OmitDuplicateNamespaces};を指定することにより、保存する際に重複する名前空間宣言を省略させることができます。 詳しくは[[#SaveOptions.OmitDuplicateNamespaces]]を参照してください。
+

          
+
#remarks
+
csprojファイルのフォーマットについて詳しくは[[programming/netfx/msbuild]]を参照してください。
+
#remarks-end
+

          
+

          
+
*XMLの出力
+
**ToStringメソッドによる文字列化
+
XDocumentやXElementに対して&msdn(netfx,member,System.Xml.Linq.XNode.ToString){ToStringメソッド};を呼びだせばXMLツリーを文字列化して取得することができます。 ToStringメソッドで文字列化した場合、XML宣言は省略されます。
+

          
+
#code(cs,ToStringメソッドを使ってXElement・XDocumentのXMLツリーを文字列化する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var root = new XElement("root",
+
                            new XElement("child1", "foo"),
+
                            new XElement("child2", "bar"));
+

          
+
    Console.WriteLine("[XElement.ToString]");
+
    // XElementに含まれるXMLツリーを文字列化
+
    Console.WriteLine(root.ToString());
+
    // 単に以下のようにした場合は自動的にToStringメソッドによる
+
    // XMLツリーの文字列化が行われる
+
    //Console.WriteLine(root);
+

          
+
    var doc = new XDocument(
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      root
+
    );
+

          
+
    Console.WriteLine("[XDocument.ToString]");
+
    // XDocumentに含まれるXMLツリーを文字列化
+
    Console.WriteLine(doc.ToString());
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
[XElement.ToString]
+
<root>
+
  <child1>foo</child1>
+
  <child2>bar</child2>
+
</root>
+
[XDocument.ToString]
+
<root>
+
  <child1>foo</child1>
+
  <child2>bar</child2>
+
</root>
+
}}
+

          
+
#remarks
+
インデントの有無やインデント幅を指定するなど、フォーマットを細かく指定して文字列化したい場合は、XmlWriterとXmlWriterSettingsを使う必要があります。 これについては[[programming/netfx/xml/1_xmlwritersettings#convert_xmltree_to_string]]で解説しています。
+
#remarks-end
+

          
+
**Saveメソッドを用いた出力 [#XDocument.Save]
+
&msdn(netfx,member,System.Xml.Linq.XDocument.Save){XDocument.Saveメソッド};・&msdn(netfx,member,System.Xml.Linq.XElement.Save){XElement.Saveメソッド};を用いればファイルや[[ストリーム>programming/netfx/stream/0_abstract]]への出力を行うこともできます。 Saveメソッドを使って出力した場合、XElement(=XMLフラグメント)の場合でも''XML宣言が付与された状態''で出力されます。
+

          
+
#code(cs,Saveメソッドを使ってXDocument・XElementのXMLツリーをファイルに保存する){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var root = new XElement("root",
+
                            new XElement("child1", "foo"),
+
                            new XElement("child2", "bar"));
+

          
+
    // XElementに含まれるXMLツリーをroot.xmlに保存
+
    root.Save("root.xml");
+

          
+
    var doc = new XDocument(
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      root
+
    );
+

          
+
    // XDocumentに含まれるXMLツリーをdoc.xmlに保存
+
    doc.Save("doc.xml");
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,root.xmlに出力される内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
  <child1>foo</child1>
+
  <child2>bar</child2>
+
</root>
+
}}
+

          
+
#code(type=output,xml,doc.xmlに出力される内容){{
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
<root>
+
  <child1>foo</child1>
+
  <child2>bar</child2>
+
</root>
+
}}
+

          
+
Saveメソッドでの出力時の動作を変更するには[[SaveOptions>#SaveOptions]]を指定します。 また、インデント幅や文字コードの指定、XML宣言の省略など、フォーマットを細かく制御したい場合は[[XmlWriterとXmlWriterSettings>programming/netfx/xml/1_xmlwritersettings]]を使って出力します。
+

          
+
#remarks
+
Saveメソッドでは、文字コードにUTF-8などを用いて出力する場合にはBOM(Byte Order Mark)が付けられます。 BOMなしで出力したい場合については[[programming/netfx/xml/1_xmlwritersettings#emit_utf8_identifier]]を参照してください。
+
#remarks-end
+

          
+
***SaveOptions [#SaveOptions]
+
XDocumentやXElementの&msdn(netfx,member,System.Xml.Linq.XNode.ToString){ToStringメソッド};、&msdn(netfx,member,System.Xml.Linq.XDocument.Save){Saveメソッド};では、出力時の動作を変えるオプションとして&msdn(netfx,type,System.Xml.Linq.SaveOptions){SaveOptions列挙体};の値を指定することができます。 SaveOptionsでは、次のいずれかの値を指定することができます。
+

          
+
|*SaveOptionsの値と出力時の動作
+
|~SaveOptionsの値|~出力時の動作|~解説|h
+
|~&msdn(netfx,member,System.Xml.Linq.SaveOptions.None){SaveOptions.None};|SaveOptionsを指定しなかった場合のデフォルトと同じ。|-|
+
|~&msdn(netfx,member,System.Xml.Linq.SaveOptions.DisableFormatting){SaveOptions.DisableFormatting};|フォーマットを行わずに出力する。&br;インデントや改行など、(XML文書としての)意味を持たない要素間のホワイトスペースなどが省略された状態で出力する。|[[解説へ>#SaveOptions.DisableFormatting]]|
+
|~&msdn(netfx,member,System.Xml.Linq.SaveOptions.OmitDuplicateNamespaces){SaveOptions.OmitDuplicateNamespaces};|重複する名前空間宣言(``&var{xxx};:xmlns="&var{yyy};"``)がある場合は、それを削除した上で出力する。|[[解説へ>#SaveOptions.OmitDuplicateNamespaces]]|
+

          
+
****SaveOptions.DisableFormatting [#SaveOptions.DisableFormatting]
+
SaveOptions.DisableFormattingを指定した場合、出力に際して要素のインデントや要素間の改行は行われなくなります。
+

          
+
#code(cs,SaveOptions.NoneとSaveOptions.DisableFormattingの出力内容の違い){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      new XElement("root",
+
        new XElement("child1", "foo"),
+
        new XElement("child2", "bar")
+
      )
+
    );
+

          
+
    doc.Save("doc-none.xml", SaveOptions.None);
+
    doc.Save("doc-df.xml", SaveOptions.DisableFormatting);
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,SaveOptions.None(デフォルトと同じ)を指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+
<root>
+
  <child1>foo</child1>
+
  <child2>bar</child2>
+
</root>
+
}}
+

          
+
#code(type=output,xml,SaveOptions.DisableFormattingを指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8" standalone="yes"?><root><child1>foo</child1><child2>bar</child2></root>
+
}}
+

          
+

          
+

          
+
&msdn(netfx,member,System.Xml.Linq.XDocument.Load){XDocument.Loadメソッド};や&msdn(netfx,member,System.Xml.Linq.XDocument.Parse){XDocument.Parseメソッド};を使ってXML文書を読み込む際に``LoadOptions.PreserveWhitespace``を指定した場合、``SaveOptions.None``や``SaveOptions.DisableFormatting``を指定してもその指定に関わらず元のホワイトスペースが維持された状態で出力されます。
+

          
+
#code(cs,LoadOptions.PreserveWhitespaceを指定して読み込んだXML文書を出力する場合){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // LoadOptions.PreserveWhitespaceを指定してXMLを読み込む
+
    var doc = XDocument.Parse(@"<?xml version=""1.0""?>
+
<root>
+
  <foo>
+
    foo
+
  </foo>
+
  <bar> bar </bar>
+

          
+
  <baz>baz
+

          
+
  </baz>
+

          
+
</root>
+
", LoadOptions.PreserveWhitespace);
+

          
+
    doc.Save("doc-none.xml", SaveOptions.None);
+
    doc.Save("doc-df.xml", SaveOptions.DisableFormatting);
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,SaveOptions.None(デフォルトと同じ)を指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
  <foo>
+
    foo
+
  </foo>
+
  <bar> bar </bar>
+

          
+
  <baz>baz
+

          
+
  </baz>
+

          
+
</root>
+
}}
+

          
+
#column
+
#code(type=output,xml,SaveOptions.DisableFormattingを指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
  <foo>
+
    foo
+
  </foo>
+
  <bar> bar </bar>
+

          
+
  <baz>baz
+

          
+
  </baz>
+

          
+
</root>
+
}}
+
#column-end
+

          
+

          
+

          
+
****SaveOptions.OmitDuplicateNamespaces [#SaveOptions.OmitDuplicateNamespaces]
+
SaveOptions.OmitDuplicateNamespacesを指定した場合、出力に際して重複する名前空間宣言が削除されます。
+

          
+
#code(cs,SaveOptions.NoneとSaveOptions.OmitDuplicateNamespacesの出力内容の違い){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsAtom + "feed",
+
        new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "entry",
+
          // 上と重複する名前空間の宣言
+
          new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
          // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
          new XElement(nsAtom + "title",
+
            new XAttribute("type", "text"),
+
            "entry 1"
+
          )
+
        )
+
      )
+
    );
+

          
+
    doc.Save("doc.xml", SaveOptions.None);
+
    doc.Save("doc-odn.xml", SaveOptions.OmitDuplicateNamespaces);
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,SaveOptions.None(デフォルトと同じ)を指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
+
    <atom:title type="text">entry 1</atom:title>
+
  </atom:entry>
+
</atom:feed>
+
}}
+
#column
+
#code(type=output,xml,SaveOptions.OmitDuplicateNamespacesを指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <atom:entry>
+
    <atom:title type="text">entry 1</atom:title>
+
  </atom:entry>
+
</atom:feed>
+
}}
+
#column-end
+

          
+
これは例えば、XML文書を構築する際に、その一部として他のメソッドやライブラリが生成するXMLツリーを組み込むような場合に有効になる場合があります。 個々のXMLツリーが名前空間宣言を含んでいても、それを組み込む親要素の側で名前空間宣言をしていれば、``SaveOptions.OmitDuplicateNamespaces``を指定することによって同一の名前空間宣言を省略させるようにすることができます。
+

          
+

          
+

          
+
``SaveOptions.OmitDuplicateNamespaces``で省略されるのは名前空間とそのプレフィックスが一致する場合に限られます。 次のように同一名前空間でも異なるプレフィックスを用いている場合は、``SaveOptions.OmitDuplicateNamespaces``を指定していても名前空間宣言は省略されません。
+

          
+
#code(cs,プレフィックスが異なる場合はSaveOptions.OmitDuplicateNamespacesを指定しても名前空間宣言は省略されない){{
+
using System;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsAtom + "feed",
+
        new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
        //                                ~~~~~~  ~~~~~~
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "entry",
+
          // 上の名前空間宣言と同一名前空間でもプレフィックスは異なるので
+
          // OmitDuplicateNamespacesを指定しても省略されない
+
          new XAttribute(XNamespace.Xmlns + "a", nsAtom.NamespaceName),
+
          //                                ~~~  ~~~~~~
+
          new XElement(nsAtom + "title",
+
            new XAttribute("type", "text"),
+
            "entry 1"
+
          )
+
        )
+
      )
+
    );
+

          
+
    doc.Save("doc.xml", SaveOptions.None);
+
    doc.Save("doc-odn.xml", SaveOptions.OmitDuplicateNamespaces);
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,SaveOptions.None(デフォルトと同じ)を指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <a:entry xmlns:a="http://www.w3.org/2005/Atom">
+
    <a:title type="text">entry 1</a:title>
+
  </a:entry>
+
</atom:feed>
+
}}
+
#column
+
#code(type=output,xml,SaveOptions.OmitDuplicateNamespacesを指定した場合の出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <a:entry xmlns:a="http://www.w3.org/2005/Atom">
+
    <a:title type="text">entry 1</a:title>
+
  </a:entry>
+
</atom:feed>
+
}}
+
#column-end
+

          
+
#remarks
+
XmlWriterを使った出力の場合、[[XmlWriterSettings.NamespaceHandlingプロパティにNamespaceHandling.OmitDuplicatesを指定する>programming/netfx/xml/1_xmlwritersettings#XmlWriterSettings.NamespaceHandling]]と、SaveOptions.OmitDuplicateNamespacesを指定した場合と同じ動作になります。
+
#remarks-end
+

          
+
**XmlWriterを用いた出力 [#XmlWriter]
+
&msdn(netfx,member,System.Xml.Linq.XDocument.Save){XDocument.Saveメソッド};および&msdn(netfx,member,System.Xml.Linq.XElement.Save){XElement.Saveメソッド};では、&msdn(netfx,type,System.Xml.XmlWriter){XmlWriter};を使った保存もサポートしています。 &msdn(netfx,type,System.Xml.XmlWriterSettings){XmlWriterSettings};と組み合わせて使うことで、出力時のフォーマットや動作を制御することができます。
+

          
+
#code(cs,XmlWriterを用いたXMLツリーの出力){{
+
using System;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 出力したいXMLツリー
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    // XmlWriterの設定
+
    var settings = new XmlWriterSettings();
+

          
+
    // 文字コードにShift_JISを用いる
+
    settings.Encoding = Encoding.GetEncoding("Shift_JIS");
+

          
+
    // インデントにタブ1文字を用いる
+
    settings.Indent = true;
+
    settings.IndentChars = "\t";
+

          
+
    // ファイル"output.xml"に出力するXmlWriterを作成する
+
    using (var writer = XmlWriter.Create("output.xml", settings)) {
+
      // XmlWriterを使ってXMLツリーを出力する
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,output.xmlに出力される内容){{
+
<?xml version="1.0" encoding="shift_jis"?>
+
<root>
+
	<foo>
+
		<bar>baz</bar>
+
	</foo>
+
	<ほげ>もげ</ほげ>
+
</root>
+
}}
+

          
+
#remarks
+
XmlWriterおよびXmlWriterSettingsは名前空間System.Xmlのクラスで、アセンブリ``System.Xml.dll``を参照に追加することによって使うことができます。 XDocumentなどが定義されている``System.Xml.Linq.dll``とは別アセンブリのクラスである点に注意してください。
+
#remarks-end
+

          
+

          
+

          
+
XmlWriterの作成は&msdn(netfx,member,System.Xml.XmlWriter.Create){XmlWriter.Createメソッド};を使います。 第一引数には出力先となるファイル名を指定できるほか、[[Stream>programming/netfx/stream/0_abstract]]やTextWriterを指定することもできるため、例えば[[MemoryStream>programming/netfx/stream/1_2_memorystream]]を用いればXMLツリーをメモリ上に展開することもできます。 [[StringWriter>programming/netfx/string/5_stringreaderwriter#System.IO.StringWriter]]を出力先とすれば、出力結果を文字列として取得することもできます。
+

          
+
#code(cs,XmlWriterとStringWriterを使ってXMLツリーを文字列として展開する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 出力したいXMLツリー
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    // 出力先となるStringWriter
+
    using (var sw = new StringWriter()) {
+
      // 出力時の設定
+
      var settings = new XmlWriterSettings() {
+
        Indent = true, // インデントする
+
        CloseOutput = false, // XmlWriterを閉じる際にベースとなるStream/TextWriterを閉じない
+
      };
+

          
+
      // StringWriterに出力するXmlWriterを作成する
+
      using (var writer = XmlWriter.Create(sw, settings)) {
+
        // XmlWriterを使ってXMLツリーを出力する
+
        doc.Save(writer);
+
      }
+

          
+
      // 出力された内容を表示する
+
      Console.WriteLine(sw.ToString());
+
    }
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<?xml version="1.0" encoding="utf-16"?>
+
<root>
+
  <foo>
+
    <bar>baz</bar>
+
  </foo>
+
  <ほげ>もげ</ほげ>
+
</root>
+
}}
+

          
+

          
+
XmlWriterを使ったXMLの出力と、XmlWriterSettingsで設定可能な内容については[[programming/netfx/xml/1_xmlwritersettings]]でより詳しく解説します。
+

          
+

          
+
//*XAnnotation
+
//*XStreamingElement
+

          
+

          
+

          
+

          
+

          
+
#navi(..)
+

          
+

          

programming/netfx/xml/1_xmlwritersettings/index.wiki.txt

current previous
1,1212 0,0
+
${smdncms:title,XmlWriterSettings}
+
${smdncms:header_title,XmlWriterSettings (System.Xml)}
+
${smdncms:keywords,XmlWriter,XmlWriterSettings}
+
#msdn(add-reference,System.Xml.Linq.dll)
+
#msdn(add-reference,System.Xml.dll)
+

          
+
#navi(..)
+

          
+
&msdn(netfx,type,System.Xml.XmlWriterSettings){System.Xml.XmlWriterSettingsクラス};を用いると、&msdn(netfx,type,System.Xml.XmlWriter){XmlWriterクラス};でのXML文書の出力時に使用する[[文字コード>#XmlWriterSettings.Encoding]]、[[インデント>#XmlWriterSettings.Indent]]や[[改行>#XmlWriterSettings.NewLineChars]]などのフォーマットを細かく指定することができます。 また、[[テキストノード内の改行文字をエンティティ化>#XmlWriterSettings.NewLineHandling]]して改行文字の種類を維持するかどうか、[[XML宣言を出力するかどうか>#XmlWriterSettings.OmitXmlDeclaration]]といった出力時の動作も指定することができます。
+

          
+
デフォルト設定のXmlWriterでは、UTF-8を用いてXMLを出力する際にBOM(Byte Order Mark)を付与しますが、XmlWriterSettingsでBOMを出力しない&msdn(netfx,type,System.Text.Encoding){Encoding};を設定することによってXmlWriterに[[BOMなしのXMLを出力させる>#emit_utf8_identifier]]ようにすることができます。
+

          
+
#relevantdocs
+

          
+
-[[programming/netfx/xml/0_generate_write]]
+
-[[programming/netfx/serialization/2_xmlserializer]]
+
-[[programming/netfx/stream/2_streamreader_streamwriter]]
+

          
+
#relevantdocs-end
+

          
+
#adunit
+

          
+
*XmlWriterとXmlWriterSettings
+
&msdn(netfx,member,System.Xml.Linq.XDocument.Save){XDocument.Saveメソッド};や&msdn(netfx,member,System.Xml.XmlDocument.Save){XmlDocument.Saveメソッド};では、直接ファイル名を指定して保存するほかにも、&msdn(netfx,type,System.Xml.XmlWriter){XmlWriter};を用いて保存することができるようになっています。
+

          
+
&msdn(netfx,type,System.Xml.XmlWriterSettings){XmlWriterSettings};で出力時のオプションを設定し、その設定に従って動作するXmlWriterをSaveメソッドに指定することで、出力時のフォーマットや動作を制御することができます。
+

          
+
#code(cs,XmlWriterを用いたXMLツリーの出力){{
+
using System;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 出力したいXMLツリー
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    // XmlWriterの設定
+
    var settings = new XmlWriterSettings();
+

          
+
    // 文字コードにShift_JISを用いる
+
    settings.Encoding = Encoding.GetEncoding("Shift_JIS");
+

          
+
    // インデントにタブ1文字を用いる
+
    settings.Indent = true;
+
    settings.IndentChars = "\t";
+

          
+
    // ファイル"output.xml"に出力するXmlWriterを作成する
+
    using (var writer = XmlWriter.Create("output.xml", settings)) {
+
      // 作成したXmlWriterを使ってXMLツリーを出力する
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,output.xmlに出力される内容){{
+
<?xml version="1.0" encoding="shift_jis"?>
+
<root>
+
	<foo>
+
		<bar>baz</bar>
+
	</foo>
+
	<ほげ>もげ</ほげ>
+
</root>
+
}}
+

          
+
*XmlWriterの作成・出力先の指定 [#XmlWriter.Create]
+
XmlWriterSettingsからXmlWriterを作成するには&msdn(netfx,member,System.Xml.XmlWriter.Create){XmlWriter.Createメソッド};を使います。 第一引数には出力先となるファイル名を指定することができるほか、[[Stream>programming/netfx/stream/0_abstract]]派生クラスや[[StreamWriter>programming/netfx/stream/2_streamreader_streamwriter]]などの&msdn(netfx,type,System.IO.TextWriter){TextWriter};派生クラスを出力先として指定することもできます。 第二引数には出力時のオプションが設定されたXmlWriterSettingsを指定します。
+

          
+
#code(cs,XmlWriter.Createメソッドを使ってXmlWriterを作成する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 出力したいXMLツリー
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    // 出力時の設定
+
    var settings = new XmlWriterSettings();
+

          
+
    /* オプションの設定は省略 */
+

          
+
    // ファイル"test.xml"に出力するXmlWriterを作成する
+
    using (var writer = XmlWriter.Create("test.xml", settings)) {
+
      doc.Save(writer); // 上記のXmlWriterを使って出力
+
    }
+

          
+
    using (var stream = new MemoryStream()) {
+
      // MemoryStreamに出力するXmlWriterを作成する
+
      using (var writer = XmlWriter.Create(stream, settings)) {
+
        doc.Save(writer); // 上記のXmlWriterを使って出力
+
      }
+
    }
+
  }
+
}
+
}}
+

          
+
このように[[MemoryStream>programming/netfx/stream/1_2_memorystream]]を用いればXMLツリーをメモリ上に展開することもできます。
+

          
+
**XmlWriterを使ったXMLツリーの文字列化 [#convert_xmltree_to_string]
+
XmlWriter.Createメソッドで[[StringWriter>programming/netfx/string/5_stringreaderwriter#System.IO.StringWriter]]を出力先に指定すれば、出力結果を文字列として取得することができます。 StringWriterを出力先とすることで、XMLツリーを文字列化する際にXmlWriterSettingsによって出力時のフォーマットを細かく指定することができます。
+

          
+
#code(cs,XmlWriterとStringWriterを使ってXMLツリーを文字列として取得する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    // 出力したいXMLツリー
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    // 出力先となるStringWriter
+
    using (var sw = new StringWriter()) {
+
      // 出力時の設定
+
      var settings = new XmlWriterSettings() {
+
        Indent = true, // インデントする
+
        CloseOutput = false, // XmlWriterを閉じる際にベースとなるStringWriterを閉じない
+
      };
+

          
+
      // StringWriterに出力するXmlWriterを作成する
+
      using (var writer = XmlWriter.Create(sw, settings)) {
+
        // XmlWriterを使ってXMLツリーを出力する
+
        doc.Save(writer);
+
      }
+

          
+
      // 出力された内容を表示する
+
      Console.WriteLine(sw.ToString());
+
    }
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<?xml version="1.0" encoding="utf-16"?>
+
<root>
+
  <foo>
+
    <bar>baz</bar>
+
  </foo>
+
  <ほげ>もげ</ほげ>
+
</root>
+
}}
+

          
+
この例では&msdn(netfx,member,System.Xml.XmlWriterSettings.CloseOutput){XmlWriterSettings.CloseOutput};に``false``を指定しています。 これにより、XmlWriterを閉じる際に出力先となるStringWriterを閉じないようになります。 このようにすることで、XmlWriterを使い終わったあともStringWriterを使い続けることができるようにしています。
+

          
+
逆にXmlWriterSettings.CloseOutputに``true``を指定すると、XmlWriterが閉じられる際に元になったStream/TextWriterも同時に閉じるようになります。
+

          
+
*XmlWriterSettingsで設定できる動作 [#XmlWriterSettings]
+
ここまでで触れてきたような内容の他にも、&msdn(netfx,type,System.Xml.XmlWriterSettings){XmlWriterSettings};では以下のような動作を設定することができます。
+

          
+
|*XmlWriterSettingsで設定できるXmlWriterの動作
+
|>|~XmlWriterSettingsのプロパティ|~動作|~解説|h
+
|~出力フォーマットに関するプロパティ|&msdn(netfx,member,System.Xml.XmlWriterSettings.Encoding){XmlWriterSettings.Encoding};|{{
+
XmlWriterでの出力時に用いるエンコーディング(&msdn(netfx,type,System.Text.Encoding);)を指定する。 特に指定しなかった場合はデフォルトでUTF-8(BOM付き)が用いられる。
+
(どちらの場合も[[XDeclaration>programming/netfx/xml/0_generate_write#XDeclaration]]や&msdn(netfx,type,System.Xml.XmlDeclaration){XmlDeclaration};によるエンコーディングの指定が''上書きされる'')
+
}}|[[#XmlWriterSettings.Encoding]]|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.Indent){XmlWriterSettings.Indent};|{{
+
``true``を指定した場合、要素のインデントと要素間の改行を行う。
+
インデント文字にはXmlWriterSettings.IndentCharsで指定された文字列を用いる。
+
改行文字にはXmlWriterSettings.NewLineCharsで指定された文字列を用いる。
+
``false``を指定した場合、インデントと改行は行われない。
+
(デフォルトは``false``: インデントしない)
+
}}|[[#XmlWriterSettings.Indent]]|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.IndentChars){XmlWriterSettings.IndentChars};|{{
+
Indentが``true``の場合に要素のインデントに用いる空白文字を指定する。
+
(デフォルトは``"  "``: U+0020 'SPACE' 半角空白が2つ)
+
}}|~|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.NewLineChars){XmlWriterSettings.NewLineChars};|{{
+
Indentが``true``の場合に要素間の改行に用いる改行文字を指定する。
+
NewLineOnAttributesが``true``の場合は、こプロパティに指定した文字列が属性間の改行にも用いられる。
+
(デフォルトは``"\n"``: U+000A 'LINE FEED' ラインフィードが1つ)
+
}}|[[#XmlWriterSettings.NewLineChars]]|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.NewLineOnAttributes){XmlWriterSettings.NewLineOnAttributes};|{{
+
``true``を指定した場合(かつIndentも``true``の場合)、属性間の改行を行い、各属性が一行ごとに記述される。
+
``false``を指定した場合、属性は要素と同じ行で一行に記述される。
+
(デフォルトは``false``: 属性間の改行を行わない)
+
}}|~|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.NewLineHandling){XmlWriterSettings.NewLineHandling};|{{
+
``&msdn(netfx,member,System.Xml.NewLineHandling.Entitize){NewLineHandling.Entitize};``を指定した場合、テキストノードの``"\r"``(U+000D 'CARRIAGE RETURN')がエンティティ化(=``"&#x26;#xD;"``)された上で出力される。
+
``&msdn(netfx,member,System.Xml.NewLineHandling.Replace){NewLineHandling.Replace};``を指定した場合、テキストノードの``"\r"``および``"\n"``(U+000A 'LINE FEED')がNewLineCharsで設定されている改行文字に統一された上で出力される。
+
この指定は属性値における改行文字・タブ文字にも影響する。
+
(デフォルトは&msdn(netfx,member,System.Xml.NewLineHandling.Replace){NewLineHandling.None};: そのままにする)
+
}}|[[#XmlWriterSettings.NewLineHandling]]|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.OmitXmlDeclaration){XmlWriterSettings.OmitXmlDeclaration};|{{
+
``true``を指定した場合、XML宣言の出力を省略する。
+
``false``を指定した場合、XML宣言の出力を省略しない。
+
(デフォルトは``false``: XML宣言を出力する)
+
}}|[[#XmlWriterSettings.OmitXmlDeclaration]]|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.NamespaceHandling){XmlWriterSettings.NamespaceHandling};|{{
+
&msdn(netfx,member,System.Xml.NamespaceHandling.OmitDuplicates){NamespaceHandling.OmitDuplicates};を指定した場合、XMLツリー内に重複する名前空間宣言が存在する場合はそれを省略して出力する。
+
&msdn(netfx,member,System.Xml.NamespaceHandling.Default){NamespaceHandling.Default};を指定した場合、重複する名前空間宣言が存在していてもそのまま出力する。
+
(デフォルトは``NamespaceHandling.Default``: 重複する名前空間宣言を省略しない)
+
}}|[[#XmlWriterSettings.NamespaceHandling]]|
+
|~出力時の検証に関するプロパティ|&msdn(netfx,member,System.Xml.XmlWriterSettings.CheckCharacters){XmlWriterSettings.CheckCharacters};|{{
+
``true``を指定した場合、CRLFを除く''C0制御文字''などのXMLとして不正な文字が含まれているかチェックし、含まれている場合は例外をスローする。
+
``false``を指定した場合、XMLとして不正な文字が含まれている場合はエンティティ化して出力し、例外はスローしない。
+
(デフォルトは``true``: チェックする)
+
}}|[[#XmlWriterSettings.CheckCharacters]]|
+
|~|&msdn(netfx,member,System.Xml.XmlWriterSettings.ConformanceLevel){XmlWriterSettings.ConformanceLevel};|{{
+
&msdn(netfx,member,System.Xml.ConformanceLevel.Document){ConformanceLevel.Document};を指定すれば、完全なXMLドキュメントとして適合するかどうかの検証が行われる。
+
&msdn(netfx,member,System.Xml.ConformanceLevel.Fragment){ConformanceLevel.Fragment};を指定すれば、XMLフラグメント(不完全なXMLの断片)として適合するかどうかの検証が行われる。
+
いずれの場合も問題があれば&msdn(netfx,type,System.Xml.XmlException){XmlException};がスローされる。
+
(デフォルトは``ConformanceLevel.Document``: 完全なXMLドキュメントとして検証する)
+
}}||
+
|~XmlWriterの出力先に関するプロパティ|&msdn(netfx,member,System.Xml.XmlWriterSettings.CloseOutput){XmlWriterSettings.CloseOutput};|{{
+
``true``を指定した場合、XmlWriterを閉じる際に元になったStream/TextWriterも同時に閉じる。
+
``false``を指定した場合、XmlWriterを閉じても元になったStream/TextWriterは開いたままにする。 この場合、XmlWriterを使用し終わったあともStream/TextWriterを継続して用いることができる。
+
(デフォルトは``false``: 元になったStream/TextWriterを開いたままにする)
+
}}|[[#convert_xmltree_to_string]]|
+

          
+
個々のプロパティを指定した場合の動作については以降で詳しく解説します。
+

          
+
**エンコーディング (XmlWriterSettings.Encoding) [#XmlWriterSettings.Encoding]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.Encoding){XmlWriterSettings.Encoding};ではXmlWriterで出力する際のエンコーディングを指定することができます。 デフォルトの状態ではUTF-8(BOM付き)が用いられます。 XmlWriterSettings.Encodingに``null``を指定することはできません。
+

          
+
XmlWriterSettings.Encodingを指定した場合、XML宣言にはそのエンコーディングが設定されます。 XMLツリーにXML宣言([[XDeclaration>programming/netfx/xml/0_generate_write#XDeclaration]]や&msdn(netfx,type,System.Xml.XmlDeclaration){XmlDeclaration};)が含まれていて``encoding``属性でなんらかのエンコーディングを指定していても、''XmlWriterSettings.Encodingの指定が優先され、XML宣言の``encoding``属性が上書きされます''。
+

          
+
#code(cs,XDeclarationの指定を上書きしてXmlWriterSettings.Encodingに指定したエンコーディングで出力する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // XML宣言でエンコーディングにutf-8を指定する
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      new XElement("root", "日本語")
+
    );
+

          
+
    // XmlWriterSettingsでエンコーディングにShift_JISを指定する
+
    var settings = new XmlWriterSettings() {
+
      Encoding = Encoding.GetEncoding("Shift_JIS"),
+
    };
+

          
+
    using (var writer = XmlWriter.Create("output.xml", settings)) {
+
      // Shift_JISでファイル"output.xml"に出力される
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,output.xmlに出力される内容){{
+
<?xml version="1.0" encoding="shift_jis" standalone="yes"?><root>日本語</root>
+
}}
+

          
+
***BOM出力の制御 [#emit_utf8_identifier]
+
&msdn(netfx,member,System.Xml.Linq.XDocument.Save){XDocument.Saveメソッド};などを用いて保存する場合、出力される内容の先頭には''BOM(Byte Order Mark)が付けられます''。 また、XmlWriterSettings.Encodingに&msdn(netfx,member,System.Text.Encoding.UTF8){Encoding.UTF8};を指定した場合や、XmlWriterSettings.Encodingをデフォルト値のままにした場合にも''BOMが付けられます''。
+

          
+
BOM無しのXMLを出力したい場合は、コンストラクタのパラメータ&var{encoderShouldEmitUTF8Identifier};に``false``を指定した&msdn(netfx,type,System.Text.UTF8Encoding){UTF8Encoding};を作成し、XmlWriterSettings.Encodingに指定します。
+

          
+
#column
+
#code(cs,UTF-8 BOM付きでXMLを出力する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root")
+
    );
+

          
+
    using (var stream = new MemoryStream()) {
+

          
+
      // エンコーディングにEncoding.UTF8を指定する
+
      var settings = new XmlWriterSettings() {
+
        Encoding = Encoding.UTF8,
+
      };
+

          
+
      using (var writer = XmlWriter.Create(stream, settings)) {
+
        // BOM付きのUTF-8でstreamに出力される
+
        doc.Save(writer);
+
      }
+

          
+
      // 出力された内容をバイト表現・文字列で表示
+
      Console.WriteLine(BitConverter.ToString(stream.ToArray()));
+
      Console.WriteLine(Encoding.UTF8.GetString(stream.ToArray()));
+
    }
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
EF-BB-BF-3C-3F-78-6D-6C-20-76-65-72-73-69-6F-6E-3D-22-31-2E-30-22-20-65-6E-63-
+
6F-64-69-6E-67-3D-22-75-74-66-2D-38-22-3F-3E-3C-72-6F-6F-74-20-2F-3E
+
<?xml version="1.0" encoding="utf-8"?><root />
+
}}
+

          
+
(BOM"```EF-BB-BF```"が先頭3バイトに出力されている)
+
#column
+
#code(cs,UTF-8 BOMなしでXMLを出力する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root")
+
    );
+

          
+
    using (var stream = new MemoryStream()) {
+
      // エンコーディングにencoderShouldEmitUTF8Identifier=falseの
+
      // UTF8Encodingを指定する
+
      var settings = new XmlWriterSettings() {
+
        Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false),
+
      };
+

          
+
      using (var writer = XmlWriter.Create(stream, settings)) {
+
        // BOMなしのUTF-8でstreamに出力される
+
        doc.Save(writer);
+
      }
+

          
+
      // 出力された内容をバイト表現・文字列で表示
+
      Console.WriteLine(BitConverter.ToString(stream.ToArray()));
+
      Console.WriteLine(Encoding.UTF8.GetString(stream.ToArray()));
+
    }
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
3C-3F-78-6D-6C-20-76-65-72-73-69-6F-6E-3D-22-31-2E-30-22-20-65-6E-63-
+
6F-64-69-6E-67-3D-22-75-74-66-2D-38-22-3F-3E-3C-72-6F-6F-74-20-2F-3E
+
<?xml version="1.0" encoding="utf-8"?><root />
+
}}
+

          
+
(BOM"```EF-BB-BF```"が出力されていない)
+
#column-end
+

          
+
&msdn(netfx,member,System.Text.UnicodeEncoding..ctor){UnicodeEncoding};(UTF-16)や&msdn(netfx,member,System.Text.UTF32Encoding..ctor){UTF32Encoding};(UTF-32)の場合も同様にコンストラクタの引数&var{byteOrderMark};によってBOMの有無を指定することができます。
+

          
+
#remarks
+
System.Text.EncodingとBOMの関連や、他のクラスにおけるBOM出力の制御については[[programming/netfx/tips/unicode_encoding_bom]]を参照してください。
+
#remarks-end
+

          
+
**XML宣言の省略 (XmlWriterSetings.OmitXmlDeclaration) [#XmlWriterSettings.OmitXmlDeclaration]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.OmitXmlDeclaration){XmlWriterSettings.OmitXmlDeclaration};に``true``を指定すると、XML文書内に[[XDeclaration>programming/netfx/xml/0_generate_write#XDeclaration]]や&msdn(netfx,type,System.Xml.XmlDeclaration){XmlDeclaration};が存在していてもXML宣言の出力を省略するようになります。
+

          
+
#code(cs,XmlWriterSetings.OmitXmlDeclarationにtrueを指定してXML宣言の出力を省略する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // XDocumentにXML宣言(XDeclaration)を含める
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      new XElement("root",
+
        new XElement("foo", "foo"),
+
        new XElement("bar")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings() {
+
      // XmlWriterでの出力時にXML宣言の出力を省略する
+
      OmitXmlDeclaration = true,
+
    };
+

          
+
    using (var writer = XmlWriter.Create("output.xml", settings)) {
+
      // XML宣言のないXML文書が"output.xml"に保存される
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,output.xmlに出力される内容){{
+
<root><foo>foo</foo><bar /></root>
+
}}
+

          
+

          
+

          
+
なお、&msdn(netfx,member,System.Xml.Linq.XDocument.ToString){XDocument.ToStringメソッド};では、文字列化に際してXML宣言が省略されます。
+

          
+
#code(cs,XDocument.ToStringメソッドを使ってXML宣言を省略した文字列を取得する){{
+
using System;
+
using System.IO;
+
using System.Text;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      // XDocumentにXML宣言を含める
+
      new XDeclaration(version: "1.0", encoding: "utf-8", standalone: "yes"),
+
      new XElement("root",
+
        new XElement("foo", "foo"),
+
        new XElement("bar")
+
      )
+
    );
+

          
+
    // ToStringメソッドを使ってXDocumentを文字列化する
+
    // (この場合、XML宣言は出力されない)
+
    Console.WriteLine(doc.ToString());
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
<root>
+
  <foo>foo</foo>
+
  <bar />
+
</root>
+
}}
+

          
+

          
+
**インデント (XmlWriterSettings.Indent, IndentChars) [#XmlWriterSettings.Indent]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.Indent){XmlWriterSettings.Indent};に``true``を指定すると要素のインデントと要素間の改行を行った上で出力するようになります。
+

          
+
インデントに用いる文字は&msdn(netfx,member,System.Xml.XmlWriterSettings.IndentChars){XmlWriterSettings.IndentChars};で指定します。 IndentCharsにはタブ(``"\t"``)や半角空白(``" "``)、全角空白(``" "``)、改行文字など、''ホワイトスペース''として扱われる文字(``&msdn(netfx,member,System.Char.IsWhiteSpace){Char.IsWhiteSpace}; = true``)からなる文字列を指定します。 それ以外の文字列を指定することもできますが、その場合は不正なXMLが出力されます。
+

          
+
#code(cs,XmlWriterSettings.IndentCharsを使ってインデント文字を変えてXMLを出力する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings() {
+
      Indent = true, // 要素のインデントと要素間の改行を行う
+
    };
+

          
+
    // 半角空白4つ単位でインデントする
+
    settings.IndentChars = new String(' ', 4);
+

          
+
    using (var writer = XmlWriter.Create("output1.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 全角空白1つ単位でインデントする
+
    settings.IndentChars = " ";
+

          
+
    using (var writer = XmlWriter.Create("output2.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // タブ1つ単位でインデントする
+
    settings.IndentChars = "\t";
+

          
+
    using (var writer = XmlWriter.Create("output3.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,output1.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
    <foo>
+
        <bar>baz</bar>
+
    </foo>
+
    <ほげ>もげ</ほげ>
+
</root>
+
}}
+
#column
+
#code(type=output,xml,output2.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
 <foo>
+
  <bar>baz</bar>
+
 </foo>
+
 <ほげ>もげ</ほげ>
+
</root>
+
}}
+
#column
+
#code(type=output,xml,output3.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
	<foo>
+
		<bar>baz</bar>
+
	</foo>
+
	<ほげ>もげ</ほげ>
+
</root>
+
}}
+
#column-end
+

          
+

          
+
#remarks
+
改行文字の指定は[[XmlWriterSettings.NewLineChars>#XmlWriterSettings.NewLineChars]]で行うことができます。
+
#remarks-end
+

          
+

          
+

          
+
XmlWriterSettingsでは''インデント文字''(空白やタブ)と''インデント幅''とを個別に指定することはできません。 あらかじめ目的の''インデント幅を持った文字列''をXmlWriterSettings.IndentCharsに指定する必要があります。
+

          
+
#code(cs,インデント文字とインデント幅によるXmlWriterSettings.IndentCharsの指定){{
+
using System;
+
using System.Linq;
+
using System.Xml;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var settings = new XmlWriterSettings();
+

          
+
    // インデント文字に半角空白、インデント幅4でインデントする
+
    settings.IndentChars = "    ";
+
    // これは以下のようにすることもできる
+
    settings.IndentChars = new string(' ', 4);
+
    settings.IndentChars = string.Concat(Enumerable.Repeat(" ", 4));
+

          
+
    // タブ2文字でインデントする
+
    settings.IndentChars = "\t\t";
+
  }
+
}
+
}}
+

          
+
#remarks
+
繰り返した文字列を作成する方法については[[programming/netfx/string/1_operations#string_repeat]]を参照してください。
+
#remarks-end
+

          
+

          
+
**要素間・属性間の改行 (XmlWriterSettings.NewLineChars, NewLineOnAttributes) [#XmlWriterSettings.NewLineChars]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.Indent){XmlWriterSettings.Indent};に``true``を指定した上で&msdn(netfx,member,System.Xml.XmlWriterSettings.NewLineChars){XmlWriterSettings.NewLineChars};を指定すると、出力時に用いる改行文字を変更することができます。
+

          
+
[[IndentChars>#XmlWriterSettings.Indent]]と同様、NewLineCharsには改行文字以外にも空白などの''ホワイトスペースとして扱われる文字''(``&msdn(netfx,member,System.Char.IsWhiteSpace){Char.IsWhiteSpace}; = true``となる文字)からなる文字列を指定することもできます。
+

          
+
#code(cs,XmlWriterSettings.NewLineCharsを使って改行文字を変えてXMLを出力する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XElement("foo", 
+
          new XElement("bar", "baz")
+
        ),
+
        new XElement("ほげ", "もげ")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings() {
+
      Indent = true, // 要素のインデントと要素間の改行を行う
+
    };
+

          
+
    // 改行文字にCRLFを用いる
+
    settings.NewLineChars = "\r\n";
+

          
+
    using (var writer = XmlWriter.Create("output1.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 改行文字に半角空白を用いる
+
    settings.NewLineChars = " ";
+

          
+
    using (var writer = XmlWriter.Create("output2.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#column
+

          
+
#code(type=output,xml,output1.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root>
+
  <foo>
+
    <bar>baz</bar>
+
  </foo>
+
  <ほげ>もげ</ほげ>
+
</root>
+
}}
+

          
+
#column
+

          
+
#code(type=output,xml,output2.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?> <root>   <foo>     <bar>baz</bar>   </foo>   <ほげ>もげ</ほげ> </root>
+
}}
+

          
+
#column-end
+

          
+

          
+

          
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.NewLineOnAttributes){XmlWriterSettings.NewLineOnAttributes};に``true``を指定すると要素間だけでなく属性間にも改行を行うようにすることができます。 属性のインデントには[[IndentChars>#XmlWriterSettings.Indent]]に指定されている文字列、改行にはNewLineCharsに指定されている文字列が用いられます。
+

          
+
#code(cs,XmlWriterSettings.NewLineOnAttributesを使って属性間を改行してXMLを出力する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XAttribute("foo", "ほげ"),
+
        new XAttribute("bar", "もげ"),
+
        new XElement("foo")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings() {
+
      Indent = true, // 要素のインデントと要素間の改行を行う
+
    };
+

          
+
    // 各属性間に改行を入れない
+
    settings.NewLineOnAttributes = false;
+

          
+
    using (var writer = XmlWriter.Create("output1.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 各属性間にも改行を入れる
+
    settings.NewLineOnAttributes = true;
+

          
+
    using (var writer = XmlWriter.Create("output2.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,output1.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root foo="ほげ" bar="もげ">
+
  <foo />
+
</root>
+
}}
+
#column
+
#code(type=output,xml,output2.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<root
+
  foo="ほげ"
+
  bar="もげ">
+
  <foo />
+
</root>
+
}}
+
#column-end
+

          
+
属性値が長くなる場合や、要素に付与する属性の数が多数になる場合は、XmlWriterSettings.NewLineOnAttributesを``true``にして属性間を改行することによって視認性を上げることができます。
+

          
+

          
+
**テキストノード・属性値の改行の処理 (XmlWriterSettings.NewLineHandling) [#XmlWriterSettings.NewLineHandling]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.NewLineHandling){XmlWriterSettings.NewLineHandlingプロパティ};ではテキストノード・属性値に含まれる改行文字をどのように扱うかを指定することができます。
+

          
+
***改行文字のエンティティ化 (NewLineHandling.Entitize)
+
&msdn(netfx,member,System.Xml.NewLineHandling.Entitize){NewLineHandling.Entitize};を指定した場合は、テキストノード内における``"\r"``(U+000D 'CARRIAGE RETURN')がエンティティ化され、```"&#x26;#xD;"```として出力されます。 ``"\n"``(U+000A 'LINE FEED')はエンティティ化されません。 テキストノード内の各改行文字がそれぞれどのようにエンティティ化されるかを表にすると次のようになります。
+

          
+
|*XmlWriterSettings.NewLineHandlingの値とエンティティ化される改行文字
+
|~XmlWriterSettings.NewLineHandlingの値|>|>|~テキストノード内の改行文字|h
+
|~|``\r``|``\n``|``\r\n``|h
+
|~NewLineHandling.None|```\r```|```\n```|```\r\n```|
+
|~NewLineHandling.Entitize|```&#x26;#xD;```|```\n```|```&#x26;#xD;\n```|
+

          
+
NewLineHandling.Entitizeを指定して改行文字をエンティティ化しておくことには次のような利点があります。 例えば、出力したXML文書が他のXMLプロセッサによって読み込まれる際に、テキストノード・属性値内の改行文字が空白文字として扱われることによって消失したり変わってしまうことを防ぐことができます。 この指定は、テキストノード・属性値内における改行文字が重要な意味を持つ場合に特に有用です。
+

          
+
#code(cs,XmlWriterSettings.NewLineHandlingにNewLineHandling.Entitizeを指定してテキストノード内のCRをエンティティ化する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root", "line1\rline2\nline3\r\nline4")
+
    );
+

          
+
    var settings = new XmlWriterSettings();
+

          
+
    // テキストノード内の改行文字をそのままにする
+
    settings.NewLineHandling = NewLineHandling.None;
+

          
+
    using (var writer = XmlWriter.Create("output-none.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // テキストノード内の"\r"(CR)をエンティティ化する
+
    settings.NewLineHandling = NewLineHandling.Entitize;
+

          
+
    using (var writer = XmlWriter.Create("output-entitize.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,output-none.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root>line1
+
line2
+
line3
+
line4</root>
+
}}
+
#column
+
#code(type=output,xml,output-entitize.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root>line1&#xD;line2
+
line3&#xD;
+
line4</root>
+
}}
+
#column-end
+

          
+

          
+

          
+
NewLineHandling.Entitizeを指定した場合は属性値も同様にエンティティ化されます。 属性値の場合、``"\r"``と``"\n"``(U+000A 'LINE FEED')の両方に加えて``"\t"``(U+0009 'CHARACTER TABULATION')がエンティティ化されます。 属性値内の各制御文字がそれぞれどのようにエンティティ化されるかを表にすると次のようになります。
+
|*XmlWriterSettings.NewLineHandlingの値とエンティティ化される制御文字
+
|~XmlWriterSettings.NewLineHandlingの値|>|>|>|~属性値内の制御文字|h
+
|~|``\r``|``\n``|``\r\n``|``\t``|h
+
|~NewLineHandling.None|```\r```|```\n```|```\r\n```|```\t```|
+
|~NewLineHandling.Entitize|```&#x26;#xD;```|```&#x26;#xA;```|```&#x26;#xD;&#x26;#xA;```|```&#x26;#x9;```|
+

          
+
#code(cs,XmlWriterSettings.NewLineHandlingにNewLineHandling.Entitizeを指定して属性値内の制御文字をエンティティ化する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XAttribute("attr", "line1\rline2\nline3\r\nline\t4")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings();
+

          
+
    // 属性値内の制御文字をそのままにする
+
    settings.NewLineHandling = NewLineHandling.None;
+

          
+
    using (var writer = XmlWriter.Create("output-none.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 属性値内の"\r"(CR)・"\n"(LF)・"\t"(TAB)をエンティティ化する
+
    settings.NewLineHandling = NewLineHandling.Entitize;
+

          
+
    using (var writer = XmlWriter.Create("output-entitize.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,output-none.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root attr="line1
+
line2
+
line3
+
line	4" />
+
}}
+

          
+
#code(type=output,xml,output-entitize.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root attr="line1&#xD;line2&#xA;line3&#xD;&#xA;line&#x9;4" />
+
}}
+

          
+

          
+
**改行文字の置換 (NewLineHandling.Replace)
+
&msdn(netfx,member,System.Xml.NewLineHandling.Replace){NewLineHandling.Replace};を指定した場合は、テキストノード内における``"\r"``(U+000D 'CARRIAGE RETURN')・``"\n"``(U+000A 'LINE FEED')および``"\r\n"``のシーケンスが[[XmlWriterSettings.NewLineChars>#XmlWriterSettings.NewLineChars]]で設定されている値へと置換されます。 一方、属性値内における改行文字に対しては置換が行われず、``NewLineHandling.Entitize``を指定した場合と同様のエンティティ化が行われます。
+

          
+
テキストノード内と属性値内の各改行文字がそれぞれどのように置換されるかを表にすると次のようになります。
+

          
+
|*XmlWriterSettings.NewLineHandlingの値と置換される改行文字
+
|~XmlWriterSettings.NewLineHandlingの値|>|>|~テキストノード内の改行文字|>|>|>|~属性値内の制御文字|h
+
|~|``\r``|``\n``|``\r\n``|``\r``|``\n``|``\r\n``|``\t``|h
+
|~NewLineHandling.None|```\r```|```\n```|```\r\n```|```\r```|```\n```|```\r\n```|```\t```|
+
|~NewLineHandling.Replace|```&var{NewLineChars};```|```&var{NewLineChars};```|```&var{NewLineChars};```|```&#x26;#xD;```|```&#x26;#xA;```|```&#x26;#xD;&#x26;#xA;```|```&#x26;#x9;```|
+
|~|>|>|(XmlWriterSettings.NewLineCharsに置換される)|>|>|>|(NewLineHandling.Entitizeを指定した場合と同様にエンティティ化される)|
+

          
+
このように、``NewLineHandling.Replace``を用いるとテキストノード内の改行文字を統一することができます。
+

          
+
#code(cs,XmlWriterSettings.NewLineHandlingにNewLineHandling.Replaceを指定してテキストノード内の改行文字を統一する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root", "line1\rline2\nline3\r\nline4")
+
    );
+

          
+
    var settings = new XmlWriterSettings();
+

          
+
    // テキストノード内の改行文字をそのままにする
+
    settings.NewLineHandling = NewLineHandling.None;
+

          
+
    using (var writer = XmlWriter.Create("output-none.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // テキストノード内の改行文字を"\n"(LF)に統一する
+
    settings.NewLineHandling = NewLineHandling.Replace;
+
    settings.NewLineChars = "\n";
+

          
+
    using (var writer = XmlWriter.Create("output-replace-tolf.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // テキストノード内の改行文字を"\r\n"(CRLF)に統一する
+
    settings.NewLineHandling = NewLineHandling.Replace;
+
    settings.NewLineChars = "\r\n";
+

          
+
    using (var writer = XmlWriter.Create("output-replace-tocrlf.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#prompt(output-none.xmlの出力内容(odコマンドによるバイナリダンプ) ){{
+
$ od -vtx1 -a output-none.xml 
+
0000000  ef  bb  bf  3c  3f  78  6d  6c  20  76  65  72  73  69  6f  6e
+
          o   ;   ?   <   ?   x   m   l  sp   v   e   r   s   i   o   n
+
0000020  3d  22  31  2e  30  22  20  65  6e  63  6f  64  69  6e  67  3d
+
          =   "   1   .   0   "  sp   e   n   c   o   d   i   n   g   =
+
0000040  22  75  74  66  2d  38  22  3f  3e  3c  72  6f  6f  74  3e  6c
+
          "   u   t   f   -   8   "   ?   >   <   r   o   o   t   >   l
+
0000060  69  6e  65  31  0d  6c  69  6e  65  32  0a  6c  69  6e  65  33
+
          i   n   e   1  cr   l   i   n   e   2  nl   l   i   n   e   3
+
0000100  0d  0a  6c  69  6e  65  34  3c  2f  72  6f  6f  74  3e
+
         cr  nl   l   i   n   e   4   <   /   r   o   o   t   >
+
0000116
+
}}
+
(ここで```cr``` = CR, ```nl``` = new line = LF)
+
#column
+
#prompt(output-replace-tolf.xmlの出力内容(odコマンドによるバイナリダンプ) ){{
+
$ od -vtx1 -a output-replace-tolf.xml 
+
0000000  ef  bb  bf  3c  3f  78  6d  6c  20  76  65  72  73  69  6f  6e
+
          o   ;   ?   <   ?   x   m   l  sp   v   e   r   s   i   o   n
+
0000020  3d  22  31  2e  30  22  20  65  6e  63  6f  64  69  6e  67  3d
+
          =   "   1   .   0   "  sp   e   n   c   o   d   i   n   g   =
+
0000040  22  75  74  66  2d  38  22  3f  3e  3c  72  6f  6f  74  3e  6c
+
          "   u   t   f   -   8   "   ?   >   <   r   o   o   t   >   l
+
0000060  69  6e  65  31  0a  6c  69  6e  65  32  0a  6c  69  6e  65  33
+
          i   n   e   1  nl   l   i   n   e   2  nl   l   i   n   e   3
+
0000100  0a  6c  69  6e  65  34  3c  2f  72  6f  6f  74  3e
+
         nl   l   i   n   e   4   <   /   r   o   o   t   >
+
0000115
+
}}
+
#column
+
#prompt(output-replace-tocrlf.xmlの出力内容(odコマンドによるバイナリダンプ) ){{
+
$ od -vtx1 -a output-replace-tocrlf.xml 
+
0000000  ef  bb  bf  3c  3f  78  6d  6c  20  76  65  72  73  69  6f  6e
+
          o   ;   ?   <   ?   x   m   l  sp   v   e   r   s   i   o   n
+
0000020  3d  22  31  2e  30  22  20  65  6e  63  6f  64  69  6e  67  3d
+
          =   "   1   .   0   "  sp   e   n   c   o   d   i   n   g   =
+
0000040  22  75  74  66  2d  38  22  3f  3e  3c  72  6f  6f  74  3e  6c
+
          "   u   t   f   -   8   "   ?   >   <   r   o   o   t   >   l
+
0000060  69  6e  65  31  0d  0a  6c  69  6e  65  32  0d  0a  6c  69  6e
+
          i   n   e   1  cr  nl   l   i   n   e   2  cr  nl   l   i   n
+
0000100  65  33  0d  0a  6c  69  6e  65  34  3c  2f  72  6f  6f  74  3e
+
          e   3  cr  nl   l   i   n   e   4   <   /   r   o   o   t   >
+
0000120
+
}}
+
#column-end
+

          
+

          
+

          
+
``NewLineHandling.Replace``を指定しても属性値の改行文字が[[NewLineChars>#XmlWriterSettings.NewLineChars]]に置換されることはなく、``NewLineHandling.Entitize``を指定した場合と同様にすべてエンティティ化されます。 改行文字だけでなく、タブ文字もエンティティ化される点に注意してください。
+

          
+
#code(cs,XmlWriterSettings.NewLineHandlingにNewLineHandling.Replaceを指定すると属性値内の改行文字はエンティティ化される){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        new XAttribute("attr", "line1\rline2\nline3\r\nline\t4")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings();
+

          
+
    // 属性値内の改行をそのままにする
+
    settings.NewLineHandling = NewLineHandling.None;
+

          
+
    using (var writer = XmlWriter.Create("output-none.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 属性値内の改行文字をエンティティ化する("\n"には置換されない)
+
    settings.NewLineHandling = NewLineHandling.Replace;
+
    settings.NewLineChars = "\n";
+

          
+
    using (var writer = XmlWriter.Create("output-replace-tolf.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 属性値内の改行文字をエンティティ化する("\r\n"には置換されない)
+
    settings.NewLineHandling = NewLineHandling.Replace;
+
    settings.NewLineChars = "\r\n";
+

          
+
    using (var writer = XmlWriter.Create("output-replace-tocrlf.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#code(type=output,xml,output-none.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root attr="line1
+
line2
+
line3
+
line	4" />
+
}}
+

          
+
#code(type=output,xml,output-replace-tolf.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root attr="line1&#xD;line2&#xA;line3&#xD;&#xA;line&#x9;4" />
+
}}
+

          
+
#code(type=output,xml,output-replace-tocrlf.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root attr="line1&#xD;line2&#xA;line3&#xD;&#xA;line&#x9;4" />
+
}}
+

          
+

          
+
**重複する名前空間宣言の処理 (XmlWriterSettings.NamespaceHandling) [#XmlWriterSettings.NamespaceHandling]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.NamespaceHandling){XmlWriterSettings.NamespaceHandlingプロパティ};では、XMLツリー内に重複する名前空間宣言(``xmlns``属性)が存在する場合にそれらをどのように扱うかを指定することができます。
+

          
+
&msdn(netfx,member,System.Xml.NamespaceHandling.OmitDuplicates){NamespaceHandling.OmitDuplicates};を指定した場合は、重複する名前空間宣言を削除し、最も上位にある名前空間宣言だけを残します。 この際、''名前空間とプレフィックスの両方が一致する名前空間宣言のみ''が削除されます。 プレフィックスが異なる名前空間宣言は別のものとして扱われ、省略されることはありません。
+

          
+
&msdn(netfx,member,System.Xml.NamespaceHandling.Default){NamespaceHandling.Default};を指定した場合は、名前空間宣言が重複していてもそのままにします。
+

          
+
#code(cs,XmlWriterSettings.NamespaceHandlingを指定して重複する名前空間宣言を省略する){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsAtom + "feed",
+
        new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "entry",
+
          // 上と重複する名前空間の宣言
+
          new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
          // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
          new XElement(nsAtom + "title",
+
            new XAttribute("type", "text"),
+
            "entry 1"
+
          )
+
        )
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings() {
+
      Indent = true,
+
    };
+

          
+
    // 重複する名前空間の宣言を省略する
+
    settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
+

          
+
    using (var writer = XmlWriter.Create("output-omitduplicates.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 重複する名前空間の宣言をそのままにする
+
    settings.NamespaceHandling = NamespaceHandling.Default;
+

          
+
    using (var writer = XmlWriter.Create("output-default.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,output-omitduplicates.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <atom:entry>
+
    <atom:title type="text">entry 1</atom:title>
+
  </atom:entry>
+
</atom:feed>
+
}}
+
#column
+

          
+
#code(type=output,xml,output-default.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
+
    <atom:title type="text">entry 1</atom:title>
+
  </atom:entry>
+
</atom:feed>
+
}}
+
#column-end
+

          
+

          
+

          
+
次の例のように、名前空間が同一でもプレフィックスが異なっている場合はそれぞれ個別の名前空間宣言とみなされ、NamespaceHandling.OmitDuplicatesを指定しても名前空間宣言の省略は行われません。
+

          
+
#code(cs,プレフィックスが異なる場合はNamespaceHandling.OmitDuplicatesを指定しても同一名前空間の宣言は省略されない){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var nsAtom = (XNamespace)"http://www.w3.org/2005/Atom";
+

          
+
    var doc = new XDocument(
+
      new XElement(nsAtom + "feed",
+
        new XAttribute(XNamespace.Xmlns + "atom", nsAtom.NamespaceName),
+
        //                                ~~~~~~  ~~~~~~
+
        new XElement(nsAtom + "title", "更新履歴 (Atom 1.0)"),
+
        new XElement(nsAtom + "entry",
+
          // 上の名前空間宣言と同一名前空間でもプレフィックスは異なるので
+
          // NamespaceHandling.OmitDuplicatesを指定しても省略されない
+
          new XAttribute(XNamespace.Xmlns + "a", nsAtom.NamespaceName),
+
          //                                ~~~  ~~~~~~
+
          new XElement(nsAtom + "title",
+
            new XAttribute("type", "text"),
+
            "entry 1"
+
          )
+
        )
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings() {
+
      Indent = true,
+
    };
+

          
+
    // 重複する名前空間の宣言を省略する
+
    settings.NamespaceHandling = NamespaceHandling.OmitDuplicates;
+

          
+
    using (var writer = XmlWriter.Create("output-omitduplicates.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    // 重複する名前空間の宣言をそのままにする
+
    settings.NamespaceHandling = NamespaceHandling.Default;
+

          
+
    using (var writer = XmlWriter.Create("output-default.xml", settings)) {
+
      doc.Save(writer);
+
    }
+
  }
+
}
+
}}
+

          
+
#column
+
#code(type=output,xml,output-omitduplicates.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <a:entry xmlns:a="http://www.w3.org/2005/Atom">
+
    <a:title type="text">entry 1</a:title>
+
  </a:entry>
+
</atom:feed>
+
}}
+
#column
+

          
+
#code(type=output,xml,output-default.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?>
+
<atom:feed xmlns:atom="http://www.w3.org/2005/Atom">
+
  <atom:title>更新履歴 (Atom 1.0)</atom:title>
+
  <a:entry xmlns:a="http://www.w3.org/2005/Atom">
+
    <a:title type="text">entry 1</a:title>
+
  </a:entry>
+
</atom:feed>
+
}}
+
#column-end
+

          
+

          
+
#remarks
+
XDocument.Saveメソッドを用いる場合は、[[SaveOptions.OmitDuplicateNamespaces>programming/netfx/xml/0_generate_write#SaveOptions.OmitDuplicateNamespaces]]を使うことでもこのプロパティと同じ結果を得ることができます。
+
#remarks-end
+

          
+

          
+

          
+
**不正な文字の処理 (XmlWriterSettings.CheckCharacters) [#XmlWriterSettings.CheckCharacters]
+
&msdn(netfx,member,System.Xml.XmlWriterSettings.NamespaceHandling){XmlWriterSettings.CheckCharactersプロパティ};では、XML内に''C0制御文字''(CR・LFを除く)など、XMLとして不正な文字が含まれているかをチェックするかどうかを指定することができます。
+

          
+
``true``を指定してチェックするようにした場合、不正な文字が含まれている際には出力時に例外&msdn(netfx,type,System.ArgumentException){ArgumentException};をスローします。
+

          
+
``false``を指定してチェックしないようにした場合、不正な文字が含まれている際にはそれをエンティティ化して出力します。 例外はスローしません。
+

          
+
#code(cs,XmlWriterSettings.CheckCharactersを指定して出力時に不正な文字が含まれていないかチェックする){{
+
using System;
+
using System.Xml;
+
using System.Xml.Linq;
+

          
+
class Sample {
+
  static void Main()
+
  {
+
    var doc = new XDocument(
+
      new XElement("root",
+
        // U+0000 'NULL'で終端されているテキストノード
+
        new XText("text\0")
+
      )
+
    );
+

          
+
    var settings = new XmlWriterSettings();
+

          
+
    // XMLとして不正な文字列が含まれているかチェックしないで出力する
+
    // (不正な文字がある場合はエンティティ化して出力する)
+
    settings.CheckCharacters = false;
+

          
+
    Console.WriteLine("[CheckCharacters = false]");
+

          
+
    using (var writer = XmlWriter.Create("output-unchecked.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    Console.WriteLine("done");
+

          
+
    // XMLとして不正な文字列が含まれているかチェックして出力する
+
    // (不正な文字がある場合は例外をスローする)
+
    settings.CheckCharacters = true;
+

          
+
    Console.WriteLine("[CheckCharacters = true]");
+

          
+
    using (var writer = XmlWriter.Create("output-checked.xml", settings)) {
+
      doc.Save(writer);
+
    }
+

          
+
    Console.WriteLine("done");
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
[CheckCharacters = false]
+
done
+
[CheckCharacters = true]
+

          
+
ハンドルされていない例外: System.ArgumentException: '.' (16 進数値 0x00) は無効な文字です。
+
   場所 System.Xml.XmlUtf8RawTextWriter.InvalidXmlChar(Int32 ch, Byte* pDst, Boolean entitize)
+
   場所 System.Xml.XmlUtf8RawTextWriter.WriteElementTextBlock(Char* pSrc, Char* pSrcEnd)
+
   場所 System.Xml.XmlUtf8RawTextWriter.WriteString(String text)
+
   場所 System.Xml.XmlWellFormedWriter.WriteString(String text)
+
   場所 System.Xml.Linq.ElementWriter.WriteElement(XElement e)
+
   場所 System.Xml.Linq.XElement.WriteTo(XmlWriter writer)
+
   場所 System.Xml.Linq.XContainer.WriteContentTo(XmlWriter writer)
+
   場所 System.Xml.Linq.XDocument.WriteTo(XmlWriter writer)
+
   場所 Sample.Main()
+
}}
+

          
+
#code(type=output,xml,output-unchecked.xmlの出力内容){{
+
<?xml version="1.0" encoding="utf-8"?><root>text&#x0;</root>
+
}}
+

          
+

          
+

          
+

          
+

          
+
#navi(..)
+

          

programming/netfx/xml/index.wiki.txt

current previous
1,9 0,0
+
${smdncms:title,XML}
+
${smdncms:keywords,XML}
+

          
+
ここでは.NET FrameworkにおけるXML文書の扱いについて解説します。
+

          
+
#adunit
+

          
+
#dir_toc
+