2017-08-06 43 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:我为一个起点添加了一些代码 –

相关问题