22

ルートのない XML ファイルがあります。これを変更することはできません。私はそれを解析しようとしていますが、それXDocument.Loadを行いません。を設定しようとしましたConformanceLevel.Fragmentが、それでも例外がスローされます。誰にもこれに対する解決策がありますか?

で試してみましXmlReaderたが、物事がめちゃくちゃで、正しく動作しません。XDocument.Loadうまく機能しますが、複数のルートを持つファイルがある場合は機能しません。

4

4 に答える 4

20

XmlReaderそれ自体はxmlフラグメントの読み取りをサポートしています-つまり

var settings = new XmlReaderSettings { ConformanceLevel = ConformanceLevel.Fragment };
using (var reader = XmlReader.Create("fragment.xml", settings))
{
  // you can work with reader just fine
}

ただしXDocument.Load、断片化された xml の読み取りはサポートしていません。

手っ取り早い方法は、 を呼び出す前にノードを 1 つの仮想ルートの下にラップすることですXDocument.Parse。お気に入り:

var fragments = File.ReadAllText("fragment.xml");
var myRootedXml = "<root>" + fragments + "</root>";
var doc = XDocument.Parse(myRootedXml);

このアプローチは、最初にファイルをメモリに読み込む必要があるため、小さな xml ファイルに限定されます。大きな文字列を連結することは、メモリ内の大きなオブジェクトを移動することを意味します。これは避けるのが最善です。

パフォーマンスが重要な場合は、優れた @Martin-Honnen の回答 ( https://stackoverflow.com/a/18203952/2440262 )で説明されているように、ノードをXDocument1 つずつ読み込む必要があります。XmlReader

XmlReader有効な xmlを反復処理するのが当然の API を使用し、パフォーマンスが問題になる場合は、代わりに結合ストリーム アプローチを使用できます。

using (var jointStream = new MultiStream())
using (var openTagStream = new MemoryStream(Encoding.ASCII.GetBytes("<root>"), false))
using (var fileStream = 
  File.Open(@"fragment.xml", FileMode.Open, FileAccess.Read, FileShare.Read))
using (var closeTagStream = new MemoryStream(Encoding.ASCII.GetBytes("</root>"), false))
{
    jointStream.AddStream(openTagStream);
    jointStream.AddStream(fileStream);
    jointStream.AddStream(closeTagStream);
    using (var reader = XmlReader.Create(jointStream))
    {
        // now you can work with reader as if it is reading valid xml
    }
}

マルチストリーム - たとえば、https: //gist.github.com/svejdo1/b9165192d313ed0129a679c927379685 を参照してください

注: XDocumentxml 全体をメモリにロードします。そのため、大きなファイルには使用しないでください。代わりにXmlReader、反復に使用し、クリスピー ビットのみXElementを経由してロードします。XNode.ReadFrom(...)

于 2013-08-12T11:54:28.037 に答える
1

XmlDocument.Load() を使用する場合は、ルート ノードでコンテンツをラップする必要があります。

または、このようなことを試すことができます...

while (xmlReader.Read())
{
    if (xmlReader.NodeType == XmlNodeType.Element)
    {
        XmlDocument d = new XmlDocument();
        d.CreateElement().InnerText = xmlReader.ReadOuterXml();
     }
}
于 2013-08-12T11:55:52.477 に答える
0

XML ドキュメントに複数のルート要素を含めることはできません。ルート要素が 1 つ必要です。あなたは一つのことをするかもしれません。すべてのfragment要素を取得してルート要素にラップし、 で解析しXDocumentます。

これは、考えられる最善かつ最も簡単なアプローチです。

于 2013-08-12T11:55:44.990 に答える