web-dev-qa-db-ja.com

C#を使用してXMLファイルを解析しますか?

XMLとC#の両方が初めてです。 "proj_title" value = heat_runまたは他の可能な値に基づいて、関連する数値を取得するために特定のxmlファイルを効率的に解析する方法を見つけようとしています。たとえば、特定のテスト実行の期間を計算します(proj_end val-proj_startval)。

ex.xml:

<proj ID="2">
      <proj_title>heat_run</proj_title>
      <proj_start>100</proj_start>
      <proj_end>200</proj_end>
</proj>

...この値はテスト実行ごとに固定されていないため、プロジェクトIDで検索することはできません。上記のファイルは巨大です:〜8mb、そしてproj_titleという名前の〜2000のタグがあります。最初にproj_title = "heat_run"ですべてのタグ名を検索し、次にC#を使用してこの特定のproj_titleのプロジェクトの開始値と終了値を取得する効率的な方法はありますか?

これが私の現在のC#コードです:

public class parser
{
     public static void Main()
     {
         XmlDocument xmlDoc= new XmlDocument();
         xmlDoc.Load("ex.xml");

         //~2000 tags w/ proj_title
         //any more efficient way to just look for proj_title="heat_run" specifically?
         XmlNodeList heat_run_nodes=xmlDoc.GetElementsByTagName("proj_title");
     }
}    
12
jerryh91

XPathを使用して、一致するすべてのノードを検索できます。次に例を示します。

XmlNodeList matches = xmlDoc.SelectNodes("proj[proj_title='heat_run']")

matchesには、基準に一致するすべてのprojノードが含まれます。 XPathの詳細: http://www.w3schools.com/xsl/xpath_syntax.asp

SelectNodesのMSDNドキュメント

8
wgraham

現代の基準では、8MBは実際にはそれほど大きくありません。個人的には、LINQ toXMLを使用します。

XDocument doc = XDocument.Load("ex.xml");
var projects = doc.Descendants("proj_title")
                  .Where(x => (string) x == "heat_run")
                  .Select(x => x.Parent) // Just for simplicity
                  .Select(x => new {
                              Start = (int) x.Element("proj_start"),
                              End = (int) x.Element("proj_end")
                          });

foreach (var project in projects)
{
    Console.WriteLine("Start: {0}; End: {1}", project.Start, project.End);
}

(明らかに、これを自分の要件に合わせて調整します。質問に基づいて何をする必要があるかは明確ではありません。)

代替クエリ:

var projects = doc.Descendants("proj")
                  .Where(x => (string) x.Element("proj_title") == "heat_run")
                  .Select(x => new {
                              Start = (int) x.Element("proj_start"),
                              End = (int) x.Element("proj_end")
                          });
14
Jon Skeet

XDocumentを使用し、LINQ APIを使用します。 http://msdn.Microsoft.com/en-us/library/bb387098.aspx

試してみた後のパフォーマンスが期待どおりでない場合は、saxパーサーを探す必要があります。 Saxパーサーはドキュメント全体をメモリにロードせず、メモリ内のすべてにxpath式を適用しようとします。イベント駆動型のアプローチでより効果的に機能し、場合によってはこれがはるかに高速になり、メモリをあまり使用しません。

おそらく周りに.NET用のsaxパーサーがあり、.NET用に自分で使用したことはありませんが、C++用に使用しました。

3
Philip Stuyck