2012-02-20 29 views

回答

0

我不認爲這是可能的。你想要對一個數據塊進行隨機訪問,該數據塊是序列化的反序列化的,所以它必須按順序訪問。 也許你可以直接修改XML文檔,這將會更快,但是你將失去使用序列化/反序列化對象樹的功能,這些對象樹更容易操作(添加/刪除對象...)

3

沒有辦法只用我想到的XmlSerializer來做你想做的事情,但是有一點額外的工作是可能的。

一個簡單的方法是按照現有的代碼序列化當天第一個項目的列表。當新數據進入時,您現在可以使用XmlDocument打開保存的xml,並一次追加單個項目的序列化。

需要注意的一件事是,如果生成的xml非常大,XmlDocument可能會變得非常大(並且可能會很慢,甚至可能會導致OutOfMemoryExceptions,因爲Pavel Kyments在註釋中註釋),在這種情況下,您可能需要調查XmlReaderXmlWriter串行追加xml。然而,總的做法將保持不變(開>連載新的用品 - >追加生成XML的>重新保存)

[編輯 - 更改代碼示例以示鏈XmlReader/XmlWriter,而不是XmlDocument做法]沿着這些線路

東西:

public static void AppendToXml(
    Stream xmlSource,    // your existing xml - could be from a file, etc 
    Stream updatedXmlDestination, // your target xml, could be a different file 
    string rootElementName,  // the root element name of your list, e.g. TestModels 
    TestModel itemToAppend)  // the item to append 
{ 
    var writerSettings = new XmlWriterSettings {Indent = true, IndentChars = " " }; 
    using (var reader = XmlReader.Create(xmlSource)) 
    using (var writer = XmlWriter.Create(updatedXmlDestination, writerSettings)) 
    { 
     while (reader.Read()) 
     { 
      switch (reader.NodeType) 
      { 
       case XmlNodeType.XmlDeclaration: 
        break; 
       case XmlNodeType.Element: 
        writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); 
        if (reader.HasAttributes) 
        { 
         while (reader.MoveToNextAttribute()) 
         { 
          writer.WriteAttributeString(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.Value); 
         } 
        } 
        if (reader.IsEmptyElement) 
         writer.WriteEndElement(); 
        break; 
       case XmlNodeType.EndElement: 
        if (reader.Name == rootElementName) 
        { 
         var serializer = new XmlSerializer(typeof(TestModel)); 
         var ns = new XmlSerializerNamespaces(); 
         ns.Add("", ""); 
         serializer.Serialize(writer, itemToAppend, ns); 
        } 
        writer.WriteEndElement(); 
        break; 
       case XmlNodeType.Text: 
        writer.WriteRaw(SecurityElement.Escape(reader.Value)); 
        break; 
       case XmlNodeType.CDATA: 
        writer.WriteCData(reader.Value); 
        break; 
      } 
     } 
    } 
} 

注:您可能希望增加對其他節點類型(此處略去了),如空白,評論,PROC支持essing指令等等。這些都遵循與上面的CDATA相同的模式:放入一個案例,調用適當的編寫器方法。

使用這種更新的方法 - 在任何給定時間內,您的內存永遠不會超過一小部分內存。

+0

我只是在輸入相同的東西。使用XmlReader或其他Xml類來直接操作XML。這不是最好的/最簡單的解決方案,這將是首先將其反序列化,但我們假設你已經擁有了,因爲你在這裏。 – sngregory 2012-02-20 08:47:27

+0

注意:對於真正的大文檔,XmlDocument將失敗,因爲它將整個文檔加載到內存中 – 2012-02-20 09:08:13

+0

@PavelKymets - 實際上。如上所述 - 在這種情況下,使用'XmlReader' /'XmlWriter'的串行方法可能更好。 – 2012-02-20 09:09:59

相關問題