2017-08-06 23 views
1

在LINQ-to-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只有一個根標籤。因此,您必須閱讀現有文件並在現有文件的中間添加其他標籤。 – 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:我爲一個起點添加了一些代碼 –

相關問題