【问题标题】:Append to the last node of xml file c#追加到xml文件c#的最后一个节点
【发布时间】:2017-12-14 17:19:07
【问题描述】:

每次收到用户的请求时,我都必须将其序列化并附加到现有的 xml 文件中,如下所示:

<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>

目前以这种方式序列化数据(效果很好):

var stringwriter = new StringWriter();
var serializer = new XmlSerializer(object.GetType());

serializer.Serialize(stringwriter, object);
var smsxmlStr = stringwriter.ToString();

var smsRecordDoc = new XmlDocument();
smsRecordDoc.LoadXml(smsxmlStr);

var smsElement = smsRecordDoc.DocumentElement;

var smsLogFile = new XmlDocument();
smsLogFile.Load("LogRecords.xml");

var serialize = smsLogFile.CreateElement("LogRecord");
serialize.InnerXml = smsElement.InnerXml;
smsLogFile.DocumentElement.AppendChild(serialize);

smsLogFile.Save("LogRecords.xml");

还有属性类

[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; }
}

但我想要做的是加载文件,导航到它的最后一个元素/节点并附加一个新的List&lt;LogRecord&gt; 并保存,这样我以后可以轻松地反序列化。 我尝试了各种使用 XPath 选择方法的方法,例如 SelectSingleNodeSelectNodes,但由于我是 c# 的初级人员,所以我无法让它们正常工作。有谁知道如何正确序列化和追加? 谢谢

【问题讨论】:

标签: c# xml xpath


【解决方案1】:

您的方法(以及迄今为止给出的大多数答案)依赖于将所有日志文件保存在内存中以便向其附加更多记录。随着日志文件的增长,这可能会导致问题(例如OutOfMemoryException 错误)。最好的办法是使用将数据从原始文件流式传输到新文件的方法。虽然我未经测试的代码中可能存在一些错误。该方法如下所示:

// 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 文件(在开始和结束时带有 &lt;LogRecords&gt; 标签?如果省略根标签,您可以简单地将新记录附加到该文件(应该非常有效)。您仍然可以通过使用正确的ConformanceLevel 创建一个XmlReader 在.Net 中读取XML。例如

var settings = new XmlReaderSettings() 
{ 
  ConformanceLevel  = ConformanceLevel.Fragment 
};
using (var reader = XmlReader.Create("LogRecords.xml", settings)) 
{ 
  // Do something with the records here
}

【讨论】:

    【解决方案2】:

    尝试使用 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; }
        }
    
    
    }
    

    【讨论】:

      【解决方案3】:

      您可以像这样使用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");
      

      【讨论】:

        猜你喜欢
        • 2011-04-02
        • 1970-01-01
        • 2022-01-14
        • 1970-01-01
        • 2021-06-21
        • 1970-01-01
        相关资源
        最近更新 更多