C#2.0でXMLドキュメントやXSDなどを処理するための最良の方法は何ですか?
どのクラスを使用するかなど。XMLドキュメントの解析と作成などのベストプラクティスは何ですか。
編集:.Net3.5の提案も歓迎します。
C#2.0でXMLドキュメントやXSDなどを処理するための最良の方法は何ですか?
どのクラスを使用するかなど。XMLドキュメントの解析と作成などのベストプラクティスは何ですか。
編集:.Net3.5の提案も歓迎します。
回答:
C#2.0での読み取りと書き込みの主な手段は、XmlDocumentクラスを介して行われます。ほとんどの設定は、受け入れるXmlReaderを介してXmlDocumentに直接ロードできます。
XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");
XmlDocument document = new XmlDocument();
document.Load(@"C:\Path\To\xmldoc.xml");
// Or using an XmlReader/XmlTextReader
XmlReader reader = XmlReader.Create(@"C:\Path\To\xmldoc.xml");
document.Load(reader);
XMLドキュメントを読む最も簡単で速い方法は、XPathを使用することです。
XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");
// Select a single node
XmlNode node = document.SelectSingleNode("/People/Person[@Name = 'Nick']");
// Select a list of nodes
XmlNodeList nodes = document.SelectNodes("/People/Person");
XSDドキュメントを操作してXMLドキュメントを検証する必要がある場合は、これを使用できます。
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd
XmlReader reader = XmlReader.Create(pathToXml, settings);
XmlDocument document = new XmlDocument();
try {
document.Load(reader);
} catch (XmlSchemaValidationException ex) { Trace.WriteLine(ex.Message); }
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd
settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler);
XmlReader reader = XmlReader.Create(pathToXml, settings);
while (reader.Read()) { }
private void settings_ValidationEventHandler(object sender, ValidationEventArgs args)
{
// e.Message, e.Severity (warning, error), e.Error
// or you can access the reader if you have access to it
// reader.LineNumber, reader.LinePosition.. etc
}
XmlWriter writer = XmlWriter.Create(pathToOutput);
writer.WriteStartDocument();
writer.WriteStartElement("People");
writer.WriteStartElement("Person");
writer.WriteAttributeString("Name", "Nick");
writer.WriteEndElement();
writer.WriteStartElement("Person");
writer.WriteStartAttribute("Name");
writer.WriteValue("Nick");
writer.WriteEndAttribute();
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
(更新1)
.NET 3.5では、XDocumentを使用して同様のタスクを実行します。ただし、違いは、Linqクエリを実行して必要なデータを正確に選択できるという利点があることです。オブジェクト初期化子を追加すると、クエリ自体で独自の定義のオブジェクトを返すクエリを作成できます。
XDocument doc = XDocument.Load(pathToXml);
List<Person> people = (from xnode in doc.Element("People").Elements("Person")
select new Person
{
Name = xnode.Attribute("Name").Value
}).ToList();
(更新2)
.NET 3.5の優れた方法は、XDocumentを使用してXMLを作成することです。これにより、コードが目的の出力と同様のパターンで表示されます。
XDocument doc =
new XDocument(
new XDeclaration("1.0", Encoding.UTF8.HeaderName, String.Empty),
new XComment("Xml Document"),
new XElement("catalog",
new XElement("book", new XAttribute("id", "bk001"),
new XElement("title", "Book Title")
)
)
);
作成します
<!--Xml Document-->
<catalog>
<book id="bk001">
<title>Book Title</title>
</book>
</catalog>
他のすべてが失敗した場合は、ここで説明した多くの例などがあるこのMSDNの記事を確認してください。 http://msdn.microsoft.com/en-us/library/aa468556.aspx
サイズによって異なります。中小規模のxmlの場合、XmlDocument(任意のC#/。NETバージョン)やXDocument(.NET 3.5 / C#3.0)などのDOMが明らかに勝者です。XSDを使用するために、あなたは使用してXMLを読み込むことができたXmlReaderを、およびXmlReaderのは(して受け入れ作成)XmlReaderSettingsを。XmlReaderSettingsオブジェクトには、xsd(またはdtd)検証を実行するために使用できるSchemasプロパティがあります。
xmlの記述についても同じことが当てはまりますが、LINQ-to-XML(XDocument)を使用してコンテンツをレイアウトする方が古いXmlDocumentよりも少し簡単であることに注意してください。
ただし、巨大なxmlの場合、DOMが大量のメモリを消費する可能性があります。その場合、XmlReader / XmlWriterを直接使用する必要があります。
最後に、xmlを操作するために、XslCompiledTransform(xsltレイヤー)を使用することをお勧めします。
xmlを操作する代わりに、オブジェクトモデルを操作することもできます。あなたが使用することができますXsd.exeではをXSDに準拠したモデルを表すクラスを作成し、単純にXMLをロードするオブジェクトとして、オブジェクト指向とそれを操作して、再度、これらのオブジェクトをシリアル化。これはXmlSerializerで行います。
nyxtomの答えはとても良いです。私はそれにいくつかのことを追加します:
XMLドキュメントへの読み取り専用アクセスが必要な場合XPathDocumentは、よりもはるかに軽量なオブジェクトですXmlDocument。
使用しての欠点はXPathDocument、使い慣れ使用できないということであるSelectNodesとSelectSingleNodeの方法をXmlNode。代わりに、IXPathNavigable提供されているツールを使用する必要があります。を使用してCreateNavigatorを作成しXPathNavigator、を使用してXPathNavigatorを作成XPathNodeIteratorし、XPathを介して見つけたノードのリストを反復処理します。これには通常、XmlDocumentメソッドよりも数行多くのコードが必要です。
ただし、XmlDocumentおよびXmlNodeクラスはを実装IXPathNavigableするため、でこれらのメソッドを使用するために記述したコードXPathDocumentは、でも機能しますXmlDocument。に対して書くことに慣れている場合IXPathNavigable、メソッドはどちらのオブジェクトに対しても機能します。(これが、メソッドシグネチャの使用XmlNodeとXmlDocumentinでFxCopによってフラグが立てられる理由です。)
嘆かわしい、XDocumentおよびXElement(とXNodeとXObject)を実装していませんIXPathNavigable。
nyxtomの答えに存在しないもう1つのことはXmlReaderです。通常はXmlReader、XMLストリームの処理を開始する前に、XMLストリームをオブジェクトモデルに解析するオーバーヘッドを回避するために使用します。代わりに、を使用して、XmlReader一度に1つのXMLノードで入力ストリームを処理します。これは本質的にSAXに対する.NETの答えです。これにより、非常に大きなXMLドキュメントを処理するための非常に高速なコードを記述できます。
XmlReader また、XMLドキュメントフラグメントを処理する最も簡単な方法を提供します。たとえば、SQLServerのFORXMLRAWオプションが返す包含要素のないXML要素のストリームです。
使用して作成するコードXmlReaderは、通常、読み取るXMLの形式と非常に緊密に結合されています。XPathを使用すると、コードをXMLにはるかに疎結合することができます。これが、一般的に正しい答えである理由です。しかし、使用する必要があるときはXmlReader、本当に必要です。
XPathNavigator CreateNavigator(this XNode node)を作成するための拡張メソッドがあることに注意してください。XPathNavigatorXNodeXDocument
まず、新しいXDocumentクラスとXElementクラスについて理解します。これらは、以前のXmlDocumentファミリよりも改善されているためです。
ただし、レガシーコード(特に以前に生成されたプロキシ)を操作するには、古いクラスを使用する必要がある場合があります。その場合、これらのXML処理クラス間で相互運用するためのいくつかのパターンに精通する必要があります。
あなたの質問は非常に広範で、詳細を説明するために1つの回答で多くを必要とするだろうと思いますが、これは私が考えた最初の一般的な回答であり、出発点として役立ちます。
101個のLinqサンプル
http://msdn.microsoft.com/en-us/library/bb387098.aspx
およびLinqtoXMLサンプル
http://msdn.microsoft.com/en-us/vbasic/bb688087.aspx
そして、LinqはXMLを簡単にできると思います。
.NET 3.5で作業していて、実験的なコードに不満がない場合は、LINQ to XSD(http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq-to-)を確認できます。xsd-alpha-0-2.aspx)。これは、XSDから.NETクラスを生成します(XSDからの組み込みルールを含む)。
次に、ファイルに直接書き込んだり、ファイルから読み取ったりして、XSDルールに準拠していることを確認できます。
使用するXMLドキュメントにXSDを使用することを強くお勧めします。
Liquid XML StudioはXSDを生成するための優れたツールであり、無料であることがわかりました。
XmlDocumentクラスを使用したXMLの記述
//itemValues is collection of items in Key value pair format
//fileName i name of XML file which to creatd or modified with content
private void WriteInXMLFile(System.Collections.Generic.Dictionary<string, object> itemValues, string fileName)
{
string filePath = "C:\\\\tempXML\\" + fileName + ".xml";
try
{
if (System.IO.File.Exists(filePath))
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlNode rootNode = doc.SelectSingleNode("Documents");
XmlNode pageNode = doc.CreateElement("Document");
rootNode.AppendChild(pageNode);
foreach (string key in itemValues.Keys)
{
XmlNode attrNode = doc.CreateElement(key);
attrNode.InnerText = Convert.ToString(itemValues[key]);
pageNode.AppendChild(attrNode);
//doc.DocumentElement.AppendChild(attrNode);
}
doc.DocumentElement.AppendChild(pageNode);
doc.Save(filePath);
}
else
{
XmlDocument doc = new XmlDocument();
using(System.IO.FileStream fs = System.IO.File.Create(filePath))
{
//Do nothing
}
XmlNode rootNode = doc.CreateElement("Documents");
doc.AppendChild(rootNode);
doc.Save(filePath);
doc.Load(filePath);
XmlNode pageNode = doc.CreateElement("Document");
rootNode.AppendChild(pageNode);
foreach (string key in itemValues.Keys)
{
XmlNode attrNode = doc.CreateElement(key);
attrNode.InnerText = Convert.ToString(itemValues[key]);
pageNode.AppendChild(attrNode);
//doc.DocumentElement.AppendChild(attrNode);
}
doc.DocumentElement.AppendChild(pageNode);
doc.Save(filePath);
}
}
catch (Exception ex)
{
}
}
OutPut look like below
<Dcouments>
<Document>
<DocID>01<DocID>
<PageName>121<PageName>
<Author>Mr. ABC<Author>
<Dcoument>
<Document>
<DocID>02<DocID>
<PageName>122<PageName>
<Author>Mr. PQR<Author>
<Dcoument>
</Dcouments>
C#プログラマーとしての私の個人的な意見は、C#でXMLを処理する最良の方法は、コードのその部分をVB.NETプロジェクトに委任することです。.NET 3.5では、VB .NETにXMLリテラルがあり、XMLの処理がはるかに直感的になります。たとえば、ここを参照してください。
(C#コードではなく、VBコードを表示するようにページを設定してください。)
プロジェクトの残りの部分はC#で記述しますが、参照されるVBプロジェクトでXMLを処理します。
nyxtom、
例1で「doc」と「xdoc」を一致させるべきではありませんか?
XDocument **doc** = XDocument.Load(pathToXml);
List<Person> people = (from xnode in **xdoc**.Element("People").Elements("Person")
select new Person
{
Name = xnode.Attribute("Name").Value
}).ToList();
Cookeyの答えは良いです...しかし、XSD(またはXML)から厳密に型指定されたオブジェクトを作成し、数行のコードでシリアル化/逆シリアル化する方法の詳細な手順は次のとおりです。
XmlNode<=> XNode<=>間でデータを変換する必要がある場合XElement
(たとえば、LINQを使用するため)、この拡張機能が役立つ場合があります。
public static class MyExtensions
{
public static XNode GetXNode(this XmlNode node)
{
return GetXElement(node);
}
public static XElement GetXElement(this XmlNode node)
{
XDocument xDoc = new XDocument();
using (XmlWriter xmlWriter = xDoc.CreateWriter())
node.WriteTo(xmlWriter);
return xDoc.Root;
}
public static XmlNode GetXmlNode(this XElement element)
{
using (XmlReader xmlReader = element.CreateReader())
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlReader);
return xmlDoc;
}
}
public static XmlNode GetXmlNode(this XNode node)
{
return GetXmlNode(node);
}
}
使用法:
XmlDocument MyXmlDocument = new XmlDocument();
MyXmlDocument.Load("MyXml.xml");
XElement MyXElement = MyXmlDocument.GetXElement(); // Convert XmlNode to XElement
List<XElement> List = MyXElement.Document
.Descendants()
.ToList(); // Now you can use LINQ
...