Нет способа сделать то, что вы хотите, используя только XmlSerializer
, который я могу придумать, но с небольшой дополнительной работой это возможно.
Простой подход к этому -сериализовать список для первого элемента (ов) дня - как делает ваш существующий код.Когда поступают новые данные, теперь вы можете открыть сохраненный xml с помощью XmlDocument
и добавить сериализацию по одному элементу за раз.
Следует отметить, что если результирующий xml очень большой,XmlDocument может стать очень большим (и может быть медленным или даже вызывать исключения OutOfMemoryException, как отмечает Павел Киментс в комментарии), в этом случае вы можете захотеть изучить XmlReader
и XmlWriter
для последовательного добавления xml.Однако общий подход остался бы прежним (open-> serialize вашего нового элемента-> добавляют сгенерированный xml-> resave)
[ EDIT - измененный пример кода для отображения цепочки 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;
}
}
}
}
Примечание: вы можете добавить поддержку других типов узлов(здесь для краткости опущено), такие как пробелы, комментарии, инструкции обработки и т. д. Все они следуют тому же шаблону, что и CDATA выше: введите регистр, вызовите соответствующий метод записи.
При таком обновленном подходе -у вас никогда не бывает больше, чем небольшое количество памяти в любой момент времени.