LINQ to XML と DOM
このセクションでは、LINQ to XML と、現在主流の XML プログラミング API である W3C ドキュメント オブジェクト モデル (DOM) との主な違いについて説明します。
XML ツリーを構築するための新しい方法
W3C DOM では、XML ツリーをボトムアップ方式で作成します。つまり、ドキュメントを作成し、要素を作成して、要素をドキュメントに追加することによって作成します。
たとえば、Microsoft の DOM の実装である XmlDocument を使用して XML ツリーを作成する場合、一般的な方法は次のようになります。
XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
XmlElement phone1 = doc.CreateElement("Phone");
phone1.SetAttribute("Type", "Home");
phone1.InnerText = "206-555-0144";
XmlElement phone2 = doc.CreateElement("Phone");
phone2.SetAttribute("Type", "Work");
phone2.InnerText = "425-555-0145";
XmlElement street1 = doc.CreateElement("Street1");
street1.InnerText = "123 Main St";
XmlElement city = doc.CreateElement("City");
city.InnerText = "Mercer Island";
XmlElement state = doc.CreateElement("State");
state.InnerText = "WA";
XmlElement postal = doc.CreateElement("Postal");
postal.InnerText = "68042";
XmlElement address = doc.CreateElement("Address");
address.AppendChild(street1);
address.AppendChild(city);
address.AppendChild(state);
address.AppendChild(postal);
XmlElement contact = doc.CreateElement("Contact");
contact.AppendChild(name);
contact.AppendChild(phone1);
contact.AppendChild(phone2);
contact.AppendChild(address);
XmlElement contacts = doc.CreateElement("Contacts");
contacts.AppendChild(contact);
doc.AppendChild(contacts);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
Dim phone1 As XmlElement = doc.CreateElement("Phone")
phone1.SetAttribute("Type", "Home")
phone1.InnerText = "206-555-0144"
Dim phone2 As XmlElement = doc.CreateElement("Phone")
phone2.SetAttribute("Type", "Work")
phone2.InnerText = "425-555-0145"
Dim street1 As XmlElement = doc.CreateElement("Street1")
street1.InnerText = "123 Main St"
Dim city As XmlElement = doc.CreateElement("City")
city.InnerText = "Mercer Island"
Dim state As XmlElement = doc.CreateElement("State")
state.InnerText = "WA"
Dim postal As XmlElement = doc.CreateElement("Postal")
postal.InnerText = "68042"
Dim address As XmlElement = doc.CreateElement("Address")
address.AppendChild(street1)
address.AppendChild(city)
address.AppendChild(state)
address.AppendChild(postal)
Dim contact As XmlElement = doc.CreateElement("Contact")
contact.AppendChild(name)
contact.AppendChild(phone1)
contact.AppendChild(phone2)
contact.AppendChild(address)
Dim contacts As XmlElement = doc.CreateElement("Contacts")
contacts.AppendChild(contact)
doc.AppendChild(contacts)
Console.WriteLine(doc.OuterXml)
このコーディング スタイルでは、XML ツリーの構造の多くを視覚的に認識できません。LINQ to XML では、このような XML ツリーの構築方法をサポートしていますが、別の方法である関数型構築もサポートしています。関数型構築では、XElement コンストラクターと XAttribute コンストラクターを使用して XML ツリーを構築します。
上記の例と同じ XML ツリーを LINQ to XML の関数型構築を使用して構築すると、次のようになります。
XElement contacts =
new XElement("Contacts",
new XElement("Contact",
new XElement("Name", "Patrick Hines"),
new XElement("Phone", "206-555-0144",
new XAttribute("Type", "Home")),
new XElement("phone", "425-555-0145",
new XAttribute("Type", "Work")),
new XElement("Address",
new XElement("Street1", "123 Main St"),
new XElement("City", "Mercer Island"),
new XElement("State", "WA"),
new XElement("Postal", "68042")
)
)
);
このように、XML ツリーを構築するコードのインデントにより、基になる XML の構造が示されます。
Visual Basic では XML リテラルが使用されるため、XML ツリーを構築するためのコードがさらに単純になります。
Dim contacts = _
<Contacts>
<Contact>
<Name>Patrick Hines</Name>
<Phone Type="Home">206-555-0144</Phone>
<Phone Type="Work">425-555-0145</Phone>
<Address>
<Street1>123 Main St</Street1>
<City>Mercer Island</City>
<State>WA</State>
<Postal>68042</Postal>
</Address>
</Contact>
</Contacts>
既存の XML ドキュメントから XML ツリーを作成する場合は、その XML ドキュメントをエディターで開いて XML をクリップボードにコピーし、Visual Studio で Visual Basic モジュールを開いて XML を直接 Visual Basic コード エディターに貼り付けることができます。
詳細については、「XML ツリーの作成」を参照してください。
XML 要素の直接操作
一般に、XML によるプログラミングで重視されるのは XML 要素であり、その属性が重要となる場合が多くあります。LINQ to XML では、XML 要素と XML 属性を直接操作できます。たとえば、次のようなことが可能です。
ドキュメント オブジェクトを一切使用せずに XML 要素を作成する。これにより、XML ツリーのフラグメントを操作する際のプログラミングが単純化されます。
T:System.Xml.Linq.XElement オブジェクトを直接 XML ファイルから読み込む。
T:System.Xml.Linq.XElement オブジェクトをファイルやストリームにシリアル化する。
これに対して、XML ドキュメントが XML ツリーの論理的コンテナーとして使用される W3C DOM では、XML ノード (要素や属性を含む) は XML ドキュメントのコンテキストで作成する必要があります。DOM で name 要素を作成するコード フラグメントを以下に示します。
XmlDocument doc = new XmlDocument();
XmlElement name = doc.CreateElement("Name");
name.InnerText = "Patrick Hines";
doc.AppendChild(name);
Dim doc As XmlDocument = New XmlDocument()
Dim name As XmlElement = doc.CreateElement("Name")
name.InnerText = "Patrick Hines"
doc.AppendChild(name)
要素を複数のドキュメントで使用する場合は、ノードをドキュメント間でインポートする必要があります。LINQ to XML では、このような複雑さを回避できます。
LINQ to XML を使用する場合、XDocument クラスを使用するのは、ドキュメントのルート レベルにコメントや処理命令を追加する場合だけです。
名前と名前空間の処理の単純化
一般に XML プログラミングでは、名前、名前空間、および名前空間プレフィックスの処理が複雑になります。LINQ to XML を使用すると、名前空間プレフィックスを処理する必要がなくなるため、名前と名前空間が単純化されます。必要に応じて名前空間プレフィックスを制御することはできますが、明示的に制御しないようにすることもできます。その場合は、シリアル中に名前空間プレフィックスが LINQ to XML によって必要に応じて割り当てられます。必要ない場合は、既定の名前空間を使用してシリアル化されます。既定の名前空間が使用された場合は、結果のドキュメントに名前空間プレフィックスは含まれません。詳細については、「XML 名前空間の使用」を参照してください。
DOM にはその他に、ノードの名前を変更できないという問題もあります。ノード名の変更が必要な場合は、新しいノードを作成し、そこにすべての子ノードをコピーする必要があります。この場合、元のノード固有の特性は失われます。LINQ to XML では、この問題を回避するために、ノードに対して XName プロパティを設定できます。
XML を読み込むための静的メソッドのサポート
LINQ to XML では、インスタンス メソッドの代わりに静的メソッドを使用して XML を読み込むことができます。これにより、読み込みと解析が簡略化されます。詳細については、「方法 : ファイルから XML を読み込む」を参照してください。
DTD の構成要素に関するサポートの削除
LINQ to XML では、XML プログラミングをさらに簡略化するために、エンティティとエンティティ参照のサポートが削除されています。エンティティの管理は複雑で、ほとんど利用されていません。これらのサポートを削除することにより、パフォーマンスが向上し、プログラミング インターフェイスが簡略化されます。LINQ to XML ツリーが設定されると、すべての DTD エンティティが展開されます。
フラグメントのサポート
LINQ to XML には、XmlDocumentFragment クラスに対応する要素はありません。ただし、XmlDocumentFragment の概念は、多くの場合、XNode の IEnumerable<T> または XElement の IEnumerable<T> として型指定されたクエリの結果によって処理できます。
XPathNavigator のサポート
LINQ to XML では、System.Xml.XPath 名前空間の拡張メソッドによって XPathNavigator がサポートされています。詳細については、「System.Xml.XPath.Extensions」を参照してください。
空白とインデントのサポート
LINQ to XML では、空白の処理が DOM より単純化されています。
一般的なシナリオでは、インデントされた XML を読み取り、メモリ内に空白のテキスト ノードなしで (つまり空白を維持せずに) XML ツリーを作成し、XML に対して何らかの操作を実行し、インデント付きで XML を保存します。書式を設定して XML をシリアル化する場合は、XML ツリー内の有意の空白のみが維持されます。これが LINQ to XML の既定の動作です。
もう 1 つのよくあるシナリオは、意図的にインデントされた XML を読み取って変更する場合です。場合によっては、このインデントを一切変更しないようにする必要があります。LINQ to XML でこれを実現するには、XML を読み込む際または解析する際に空白を維持し、XML をシリアル化するときに書式設定を無効にします。
LINQ to XML では、空白は XText ノードとして格納されます。DOM とは違って、特殊なノード型である Whitespace は使用されません。
注釈のサポート
LINQ to XML 要素は、注釈の拡張可能なセットをサポートしています。このサポートは、スキーマの情報、要素が UI にバインドされているかどうかの情報、またはアプリケーション固有のその他の情報など、要素に関するさまざまな情報を追跡する場合に利用できます。詳細については、「LINQ to XML の注釈」を参照してください。
スキーマ情報のサポート
LINQ to XML では、System.Xml.Schema 名前空間の拡張メソッドによって XSD 検証がサポートされています。これにより、XML ツリーが XSD に準拠しているかどうかを検証できます。また、スキーマ検証後の情報セット (PSVI) を使用して XML ツリーを設定できます。詳細については、「方法 : XSD を使用して検証する (LINQ to XML)」および「Extensions」を参照してください。