LINQ to XML APIを使用してXMLを構築する

最近まで、私はXMLファイルを扱うのが本当に好きではありませんでした。可能な限りこれを避け、標準のアプリケーション構成ファイルに置き換えるだけでした。 しかし、データ交換を使用する必要がある場合、XMLからの脱出はありませんでした。 少量の情報を変換または読み取るために、大量のコードを作成する必要がありました。 はい、それはXMLドキュメントオブジェクトモデル(DOM)APIです。



XML DOM APIの例



次のメッセージを受信する必要があります。

< Groups >

< Group Id ="523063B0-47C0-4ABE-8D38-4A449137A00B" DepartmentId ="D939743F-BFF7-41E4-9A1B-1193EEFF0486" >

< Name > 555A </ Name >

< Course > 5 </ Course >

</ Group >

</ Groups >








これを行うには、かなり単純ですが、膨大なコードを記述する必要があります。

private sealed class Nodes

{

public const string Root = "Groups" ;



// Attributes.

public const string Group = "Group" ;

public const string Id = "Id" ;

public const string DepartmentId = "DepartmentId" ;



// Elements.

public const string Name = "Name" ;

public const string Course = "Course" ;

}



// Create XML document.

XmlDocument document = new XmlDocument ();



// Create root element.

XmlElement rootElement = document.CreateElement( Nodes .Root);



// Create Group element.

XmlElement groupElement = document.CreateElement( Nodes .Group);



// Create attributes.

XmlAttribute idAttribute = document.CreateAttribute( Nodes .Id);

idAttribute.InnerText = "523063B0-47C0-4ABE-8D38-4A449137A00B" ;

groupElement.Attributes.Append(idAttribute);



XmlAttribute departmentIdAttribute = document.CreateAttribute( Nodes .DepartmentId);

departmentIdAttribute.InnerText = "D939743F-BFF7-41E4-9A1B-1193EEFF0486" ;

groupElement.Attributes.Append(departmentIdAttribute);



// Create elements.

XmlElement nameElement = document.CreateElement( Nodes .Name);

nameElement.InnerText = "555A" ;

groupElement.AppendChild(nameElement);



XmlElement courseElement = document.CreateElement( Nodes .Course);

courseElement.InnerText = "5" ;

groupElement.AppendChild(courseElement);



rootElement.AppendChild(groupElement);

document.AppendChild(rootElement);








そのようなコードを書いたり、分解したり、維持したりするのはあまり楽しいことではないことに同意してください。



このコードを使用すると、結果のXML構造を把握することはできません。 各要素または属性には常に3つのステップがあります。作成、InnerTextプロパティの設定、および既存の要素またはドキュメントへの追加です。 また、XmlDocumentを作成せずに、単純に要素を作成することは不可能であり、これはしばしば十分に必要です。



幸いなことに、Microsoftは統合されたLINQ to XMLクエリを実行する機能だけでなく、XML DOM APIを再設計しました。

今日はこれについてもっとお話ししたいと思います。 これを行うには、次の名前空間を接続する必要があります。

using System.Collections.Generic;

using System.Linq;

using System.Xml.Linq;








先ほど言ったように、標準のDOMモデルの欠点の1つは、結果のXMLファイルの構造が読みにくいことです。 LINQ to XML APIは、機能構築と呼ばれる新しい手法を提供することにより、この問題を解決します。 機能設計により、XMLオブジェクトを構築し、その値を初期化することができます-多数のオーバーロードされたコンストラクターにより、単一のステートメントで同時に。



LINQ to XML APIを使用した場合の既知のXMLファイルの構築方法を見てみましょう。

XElement document = new XElement ( Nodes .Root,

new XElement ( Nodes .Group,

new XAttribute ( Nodes .Id, "523063B0-47C0-4ABE-8D38-4A449137A00B" ),

new XAttribute ( Nodes .DepartmentId, "D939743F-BFF7-41E4-9A1B-1193EEFF0486" ),

new XElement ( Nodes .Name, "555A" ),

new XElement ( Nodes .Course, 5)));






まあどう? どのコードが読みやすいですか? 答えは明らかです。



オブジェクトモデル









XObjectXNode、およびXContainerクラスは抽象であるため、作成できません。

XAttributeクラス-XNodeから継承されない、つまり ノードではなく、キーと値のペアを表す単純なコレクションアイテムです。

XNodeおよびXElementクラスは、 XNodeから継承されたノードを含むことができる唯一のクラスです



XDocument



LINQ to XML APIでは、XMLツリーまたはそのフラグメントを作成するためにXDocumentを作成する必要はありません。

XDocument document = new XDocument ();

Console .WriteLine(document.ToString());






空の結果が得られます。



XDocument自体には、広告( XDeclaration )、タイプ作成( XDocumentType )、または処理命令( XProcessingInstruction )をドキュメントに追加する機能のみがあります



ドキュメントのコンテンツを読み込むための静的メソッドがあり、あらゆる種類のオーバーロードオプションがあります。

public static XDocument Load( Stream stream);

public static XDocument Load( string uri);

public static XDocument Load( TextReader textReader);

public static XDocument Load( XmlReader reader);

public static XDocument Load( Stream stream, LoadOptions options);

public static XDocument Load( string uri, LoadOptions options);

public static XDocument Load( TextReader textReader, LoadOptions options);

public static XDocument Load( XmlReader reader, LoadOptions options);






また、ドキュメントを保存するには:

public void Save( Stream stream);

public void Save( string fileName);

public void Save( TextWriter textWriter);

public void Save( XmlWriter writer);

public void Save( Stream stream, SaveOptions options);

public void Save( string fileName, SaveOptions options);

public void Save( TextWriter textWriter, SaveOptions options);






要素( XElement )にも同じメソッドがあります。



XDocumentは、バージョン番号とエンコードを含むドキュメントの広告を設定する必要がある場合にのみ使用します。



XDeclaration



XDeclarationオブジェクトは、あなたが推測したとおり 、宣言を含み、ドキュメントに追加されますが、コンパイラーは要素( XElement )に宣言を追加できますが、これは目に見える結果を与えません。

XDocument document = new XDocument (

new XDeclaration ( "1.0" , "UTF-8" , "yes" ));

Console .WriteLine(document.ToString());






このコードも行を表示しませんが、デバッガーを見ると、宣言が追加されています:







XDocumentクラスのSave()メソッドを使用すると、宣言が表示されます。



XElement



最も一般的に使用されるAPIオブジェクト。

多くのデザイナーがいます。そのうち2人を検討してください。



public XElement ( XName name, object content);

public XElement ( XName name, params object [] content);






最初のコンストラクターは、要素に子がなく、その値のみを設定する最も単純なケースです。2番目のコンストラクター-要素、属性、処理命令、コメント( XComment )などの子を持つ



最も単純な要素を作成します。

XElement element = new XElement ( "Element" , 777);

Console .WriteLine(element.ToString());

Console .WriteLine(( int )element);






結果:

< Element > 777 </ Element >

777






ご覧のとおり、要素の明示的なキャストの再定義により、値へのアクセスがさらに容易になりました;値を確認するには、元の型に要素をキャストするだけで十分です。 XElementは、すべての単純型の明示的なキャストをオーバーライドします。 これで、 Valueプロパティも不要になりました。

コンストラクターはXNameを必要としますが、文字列を渡しますか? そして、私はあなたに答えます:文字列は暗黙的にXNameオブジェクトにキャストされます。 実際、 XNameは文字列であり、名前空間( XNamespace )を指定する機能のみがあります。



オブジェクトからXMLを作成するより詳細な例を示します。

public sealed class Teacher

{

public Guid Id;

public string FirstName;

public string LastName;

}



IEnumerable < Teacher > teachers = new []

{

new Teacher () { Id = Guid .NewGuid(), FirstName = "" , LastName = "" },

new Teacher () { Id = Guid .NewGuid(), FirstName = "" , LastName = "" }

};



XElement elements = new XElement ( "Teachers" ,

teachers.Select(t => new XElement ( "Teacher" ,

new XAttribute ( "Id" , t.Id),

new XElement ( "FirstName" , t.FirstName),

new XElement ( "LastName" , t.LastName))));



Console .WriteLine(elements.ToString());






その結果、次のことができます。

< Teachers >

< Teacher Id ="80321d66-ee4b-4b55-ace8-3892b682d483" >

< FirstName > </ FirstName >

< LastName > </ LastName >

</ Teacher >

< Teacher Id ="33f58b19-1bbb-468f-acee-961edb63ce0b" >

< FirstName > </ FirstName >

< LastName > </ LastName >

</ Teacher >

</ Teachers >






XAttribute



前述したように、これは要素属性のコレクションのキーと値のペアです。 属性の作成と要素への追加は、非常に簡単なタスクです。

XAttribute attribute = new XAttribute ( "Id" , Guid .NewGuid());

XElement element = new XElement ( "Teachers" );

element.Add(attribute);

Console .WriteLine(element.ToString());






または:

XElement element = new XElement ( "Teachers" ,

new XAttribute ( "Id" , Guid .NewGuid()));

Console .WriteLine(element.ToString());






結果は同じです:

< Teachers Id ="713c6cbf-f698-42fd-b5fc-74415b93d824" />







XComment



コメントを作成して追加しても、問題は発生しません。

XElement teacherElement = new XElement ( "Teacher" ,

new XComment ( "Teacher element" ));

Console .WriteLine(teacherElement.ToString());






結果:

< Teacher >

<!--Teacher element-->

</ Teacher >








おわりに



この段階で、仕上げたいと思います。 はい、処理命令の例を使用したり、ドキュメントタイプやその他のモデルクラスを作成することは検討しませんでしたが、この知識は単純なXMLドキュメントと複雑なXMLドキュメントの両方を作成するのに十分です。



次回の記事では、XML文書の内容の通過を検討する予定です。



All Articles