C# 附加到xml文件c的最后一个节点
每次收到用户的请求时,我都必须将其序列化并附加到现有的xml文件中,如下所示:C# 附加到xml文件c的最后一个节点,c#,xml,xpath,C#,Xml,Xpath,每次收到用户的请求时,我都必须将其序列化并附加到现有的xml文件中,如下所示: <LogRecords> <LogRecord> <Message>Some messagge</Message> <SendTime>2017-12-13T22:04:40.1109661+01:00</SendTime> <Sender>Sender</Sender> <Rec
<LogRecords>
<LogRecord>
<Message>Some messagge</Message>
<SendTime>2017-12-13T22:04:40.1109661+01:00</SendTime>
<Sender>Sender</Sender>
<Recipient>Name</Recipient>
</LogRecord>
<LogRecord>
<Message>Some message too</Message>
<SendTime>2017-12-13T22:05:08.5720173+01:00</SendTime>
<Sender>sender</Sender>
<Recipient>name</Recipient>
</LogRecord>
</LogRecords>
属性类
[XmlRoot("LogRecords")]
public class LogRecord
{
public string Message { get; set; }
public DateTime SendTime { get; set; }
public string Sender { get; set; }
public string Recipient { get; set; }
}
但我要做的是加载文件,导航到文件的最后一个元素/节点,并附加一个新列表并保存,以便以后可以轻松地反序列化。
我尝试过使用XPath选择方法的各种方法,如SelectSingleNode和SelectNodes,但由于我是c语言的初级,我还没有设法使它们正常工作。有人知道如何正确地序列化和附加吗?
谢谢尝试使用xml linq:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
LogRecord record = doc.Descendants("LogRecord").Select(x => new LogRecord()
{
Message = (string)x.Element("Message"),
SendTime = (DateTime)x.Element("SendTime"),
Sender = (string)x.Element("Sender"),
Recipient = (string)x.Element("Recipient")
}).OrderByDescending(x => x.SendTime).FirstOrDefault();
}
}
public class LogRecord
{
public string Message { get; set; }
public DateTime SendTime { get; set; }
public string Sender { get; set; }
public string Recipient { get; set; }
}
}
您可以像这样使用XDocument来执行它
XDocument doc = XDocument.Load("LogRecords.xml");
//Append Node
XElement logRecord = new XElement("LogRecord");
XElement message = new XElement("Message");
message.Value = "Message";
XElement sendTime = new XElement("SendTime");
sendTime.Value = "SendTime";
XElement sender = new XElement("Sender");
sender.Value = "Sender";
XElement recipient = new XElement("Recipient");
recipient.Value = "Recipient";
logRecord.Add(message);
logRecord.Add(sendTime);
logRecord.Add(sender);
logRecord.Add(recipient);
doc.Element("LogRecords").Add(logRecord);
//Append Node
doc.Save("LogRecords.xml");
您的方法和迄今为止给出的大多数答案都依赖于将所有日志文件都存储在内存中,以便向其追加更多记录。随着日志文件的增长,这可能会导致诸如OutOfMemoryException错误之类的问题。最好的办法是使用将数据从原始文件流式传输到新文件的方法。虽然我未经测试的代码中可能有一些bug。该方法类似于以下内容:
// What you are serializing
var obj = default(object);
using (var reader = XmlReader.Create("LogRecords.xml"))
using (var writer = XmlWriter.Create("LogRecords2.xml"))
{
// Start the log file
writer.WriteStartElement("LogRecords");
while (reader.Read())
{
// When you see a record in the original file, copy it to the output
if (reader.NodeType == XmlNodeType.Element && reader.LocalName == "LogRecord")
{
writer.WriteNode(reader.ReadSubtree(), false);
}
}
// Add your additional record(s) to the output
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(writer, obj);
// Close the tag
writer.WriteEndElement();
}
// Replace the original file with the new file.
System.IO.File.Delete("LogRecords.xml");
System.IO.File.Move("LogRecords2.xml", "LogRecords.xml");
要考虑的另一个想法,日志文件是否需要是一个有效的XML文件,标签在开始和结束时?如果省略根标记,您可以简单地将新记录附加到文件的底部,这应该是非常有效的。您仍然可以通过创建具有正确一致性级别的XmlReader在.Net中读取XML。比如说
var settings = new XmlReaderSettings()
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var reader = XmlReader.Create("LogRecords.xml", settings))
{
// Do something with the records here
}
查看或了解一些可能有效的技巧。要反序列化什么?如果所有的数据都是正确的,那么。如果只有最后一个元素,则使用list-sic!并从中提取最后一个元素。或者在循环中使用ReadToFollowing,直到到达最后一个元素。
var settings = new XmlReaderSettings()
{
ConformanceLevel = ConformanceLevel.Fragment
};
using (var reader = XmlReader.Create("LogRecords.xml", settings))
{
// Do something with the records here
}