通常,我使用下面的代碼將對象序列化爲XML文件。每天,我都會在不同的時間段內將約100-1000個新項目添加到此列表中。如何在沒有反序列化舊數據的情況下將新項添加到序列化的xml數據中?
var xmlSerializer = new XmlSerializer(typeof(List<TestModel>));
xmlSerializer.Serialize(stream, list);
如何新項目追加到序列化的XML數據,而不反序列化舊的數據?
感謝,
通常,我使用下面的代碼將對象序列化爲XML文件。每天,我都會在不同的時間段內將約100-1000個新項目添加到此列表中。如何在沒有反序列化舊數據的情況下將新項添加到序列化的xml數據中?
var xmlSerializer = new XmlSerializer(typeof(List<TestModel>));
xmlSerializer.Serialize(stream, list);
如何新項目追加到序列化的XML數據,而不反序列化舊的數據?
感謝,
您可以序列化對象到內存並追加到現有文件。還可以看看MS文章Efficient Techniques for Modifying Large XML Files,其中顯示了兩種適用於您的情況的技術。
我不認爲這是可能的。你想要對一個數據塊進行隨機訪問,該數據塊是序列化的和反序列化的,所以它必須按順序訪問。 也許你可以直接修改XML文檔,這將會更快,但是你將失去使用序列化/反序列化對象樹的功能,這些對象樹更容易操作(添加/刪除對象...)
沒有辦法只用我想到的XmlSerializer
來做你想做的事情,但是有一點額外的工作是可能的。
一個簡單的方法是按照現有的代碼序列化當天第一個項目的列表。當新數據進入時,您現在可以使用XmlDocument
打開保存的xml,並一次追加單個項目的序列化。
需要注意的一件事是,如果生成的xml非常大,XmlDocument可能會變得非常大(並且可能會很慢,甚至可能會導致OutOfMemoryExceptions,因爲Pavel Kyments在註釋中註釋),在這種情況下,您可能需要調查XmlReader
和XmlWriter
串行追加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相同的模式:放入一個案例,調用適當的編寫器方法。
使用這種更新的方法 - 在任何給定時間內,您的內存永遠不會超過一小部分內存。
我只是在輸入相同的東西。使用XmlReader或其他Xml類來直接操作XML。這不是最好的/最簡單的解決方案,這將是首先將其反序列化,但我們假設你已經擁有了,因爲你在這裏。 – sngregory 2012-02-20 08:47:27
注意:對於真正的大文檔,XmlDocument將失敗,因爲它將整個文檔加載到內存中 – 2012-02-20 09:08:13
@PavelKymets - 實際上。如上所述 - 在這種情況下,使用'XmlReader' /'XmlWriter'的串行方法可能更好。 – 2012-02-20 09:09:59