0

私は.Net 2.0を使用しなければならないことにちょっと行き詰まっているので、LINQ xmlは利用できませんが、比較する方法に興味があります...

基本的にビルド構成であるいくつかの大きな XML ファイル (それぞれ約 10 メガバイト) をダウンロード、抽出、および比較するための内部プログラムを作成する必要がありました。私は最初にMicrosoft の XML diff/patchなどのライブラリを使用しようとしましたが、空白や名前空間などを無視しても、ファイルの比較に 2 ~ 3 分かかりました (私はそれぞれの無視を一度に 1 つずつテストして、何が原因であるかを調べてみました)。最速)。私は自分のアイデアを実装しようとしました - XmlDocument オブジェクトからのノードのリスト、ルートの直接の子孫 (ちなみに 45000 の子) のキーの辞書は、XML ドキュメント内のノードの位置を示すために int を指していました... すべてがかかりました実行するのに少なくとも 2 分。

最終的な実装は 1 ~ 2 秒で完了します。数行のコンテキストを使用して diff のシステム プロセス コールを作成し、それらの結果を保存して表示しました (私たちの開発マシンには cygwin が含まれています。ありがたいことに)。

これを行うには、プレーンテキストの差分と同じくらい高速な、より優れた XML 固有の方法があると思わずにはいられません。特に、私が本当に興味を持っているのは、各ダイレクトの子である Name 要素だけだからです。子孫であり、私の目的のためにファイルの 4/5 を捨てることができます (どのファイルが含まれているかを知る必要があるだけで、言語やバージョンに関連するものは何も必要ありません)

したがって、XML が普及しているのと同じように、誰かが同じようなことをしなければならなかったに違いありません。これらの大きな XML を比較するための高速で効率的な方法は何ですか? (できればオープンソースまたは無料)

編集: ノードのサンプル - 欠落している Name 要素を見つけるだけで済みます (45k 以上のノードもあります)

<file>
     <name>SomeFile</name>
     <version>10.234</version>
     <countries>CA,US</countries>
     <languages>EN</languages>
     <types>blah blah</types>
     <internal>N</internal>
</file>
4

2 に答える 2

0

XML の差分は、さまざまな方法で実行できます。ただし、詳細についてはあまり具体的ではありません。ファイルが大きく、必要な情報は 5 分の 4 だけです。

さて、アルゴリズムは次のとおりです。

  • ドキュメントを正規化し、重要な情報に減らします。
  • 結果を保存します。
  • 結果を比較します。

そして実装

  • 効率的なXmlReader APIを使用して、情報のプレーン テキスト表現を生成します。なぜプレーンテキスト表現なのか? 差分ツールは、プレーン テキストがあるという前提に基づいているためです。そして私たちの目玉もそうです。なぜXmlReaderですか?SAX を使用することもできます。これはメモリ効率が高く、XmlReaderより効率的です。そのプレーンテキストファイルの正確な仕様については...十分な情報が含まれていません。
  • プレーン テキスト ファイルを一時ディレクトリに保存します。
  • GnuWin32 diffなどのコマンドライン diff ユーティリティを使用して、いくつかの diff 出力を取得します。ええ、私は知っています、純粋で適切ではありませんが、箱から出してすぐに動作し、コーディングを行う必要はありません. C# diff API に精通している場合 (私は知りません)、もちろん、代わりにその API を使用してください。
  • 一時ファイルを削除します。(または、再利用する場合はオプションで保管してください。)
于 2012-06-06T20:33:12.247 に答える
0
XmlDocument source = new XmlDocument();
source.Load("source.xml");
Dictionary<string, XmlNode> files = new Dictionary<string, XmlNode>();
foreach(XmlNode file in source.SelectNodes("//file"))
    files.Add(file.SelectSingleNode("./name").InnerText, file);

XmlDocument source2 = new XmlDocument();
source2.Load("source2.xml");
XmlNode value;
foreach(XmlNode file in source2.SelectNodes("//file"))
    if (files.TryGetValue(file.SelectSingleNode("./name").InnerText, out value))
      // This file is both in source and source2.
    else
      // This file is only in source2.

あなたが何を望んでいるのか正確にはわかりませんが、この例があなたの探求に役立つことを願っています.

于 2012-06-06T20:29:23.210 に答える