2017-08-06 7 views
1

LINQ-to-XMLにXMLファイルを追加する標準的な方法は、XMLファイルを読み込み、メモリ内のドキュメントを変更し、ファイル全体をゼロから書き出すことです。XMLを最初から書き込むことなくファイルに追加できますか?

XDocument doc = XDocument.Load("pathToDoc.xml"); 
doc.Root.Add(new XElement(namespace + "anotherChild", new XAttribute("child-id", childId))); 
doc.Save("pathToDoc.xml"); 

あるいは、FileStream有する:例えば

using (FileStream fs = new FileStream("pathToDoc.xml", FileMode.Open, FileAccess.ReadWrite)) { 
    XDocument doc = XDocument.Load(fs); 
    doc.Root.Add(new XElement(namespace + "anotherChild", new XAttribute("child-id", childId))); 

    fs.SetLength(0); 
    using (var writer = new StreamWriter(fs, new UTF8Encoding(false))) { 
     doc.Save(writer); 
    } 
} 

しかしながら、両方の場合において、既存のXML文書は、メモリにロードされているメモリで変更し、その後ゼロから書き込ま XMLファイルに追加します。小さなXMLファイルの場合、これは問題ありませんが、数百または数千のノードを持つ大きなファイルの場合、これは非常に非効率的なプロセスのようです。 XDocument(またはおそらくXmlWriterのようなもの)を既存のXML文書に追加するだけでなく、ゼロから始めるのではなく、追加のノードを追加する方法はありますか?

+1

よく形成されたXMLが唯一の1つのルートタグを持っています。したがって、既存のファイルを読み、既存のファイルの途中にタグを追加する必要があります。 – jdweng

+0

はい、しかし、良いシリアライザが正しい場所を探して追加するインテリジェンスを持っていることを望みます。 – Jez

+0

XMLファイルは単なるテキストファイルなので、テキストファイルの途中に簡単に挿入する方法はありません。 [.NETでファイルの途中に行を追加する](https://stackoverflow.com/q/2044365/3744182)を参照してください。しかし、ルート要素の終了タグの直前に挿入するので、[XMLの終わりに新しいノードを追加する最速の方法](https://stackoverflow.com/q/849043/3744182)を参照してください。重複 – dbc

答えて

1

これは、追加要素を追加する必要がある位置によって異なります。もちろん、終了する"</root>"タグを削除し、追加の要素を書き込んだり、"</root>"を再度追加するものを実装することもできます。しかし、このようなコードは目的に合わせて高度に最適化されているため、おそらくライブラリを見つけることはできません。

あなたのコードは(<root/>が存在しないことを想定し、入力チェックせずに、迅速かつ汚い)次のようになります。

using System.IO; 
using System.Xml.Linq; 

namespace XmlAddElementWithoutLoading 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var rootelement = "root"; 
      var doc = GetDocumentWithNewNodes(rootelement); 
      var newNodes = GetXmlOfNewNodes(doc); 

      using (var fs = new FileStream("pathToDoc.xml", FileMode.Open, FileAccess.ReadWrite)) 
      { 
       using (var writer = new StreamWriter(fs)) 
       { 
        RemoveClosingRootNode(fs, rootelement); 
        writer.Write(newNodes); 
        writer.Write("</"+rootelement+">"); 
       } 
      } 
     } 

     private static void RemoveClosingRootNode(FileStream fs, string rootelement) 
     { 
      fs.SetLength(fs.Length - ("</" + rootelement + ">").Length); 
      fs.Seek(0, SeekOrigin.End); 
     } 

     private static string GetXmlOfNewNodes(XDocument doc) 
     { 
      var reader = doc.Root.CreateReader(); 
      reader.MoveToContent(); 
      return reader.ReadInnerXml(); 
     } 

     private static XDocument GetDocumentWithNewNodes(string rootelement) 
     { 
      var doc = XDocument.Parse("<" + rootelement + "/>"); 
      var childId = "2"; 
      XNamespace ns = "namespace"; 
      doc.Root.Add(new XElement(ns + "anotherChild", new XAttribute("child-id", childId))); 
      return doc; 
     } 
    } 
} 
+0

私は、XML文書の親要素の最後に要素を追加したいだけでは比較的一般的だと思っていたでしょうか? – Jez

+0

@Jez:出発点にいくつかのコードを追加しました –

関連する問題