Read xml element while deserializing c#

巧了我就是萌 提交于 2019-12-11 07:29:31

问题


I have an xml document, where i serialize data dinamically, appending new data if i have a new request. The object properties i serialize are like this

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

Serializing is done in this way :

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");

While serializing i use LogFile.CreateElement("LogRecord") and my xml file looks like this :

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

When i try to deserialize like this

 XmlSerializer deserializer = new XmlSerializer(typeof(LogRecord));
 TextReader reader = new StreamReader("LogRecords.xml");
 object obj = deserializer.Deserialize(reader);
 LogRecord records = (LogRecord)obj;
 reader.Close();

I get null value for each property Message, Sender Recipient and a random value for SendTime, and i know it's because it doesn't recognise the XmlElement LogRecord i added while serializing.. Is there any way to read this xml element so i can take the right property values?

Ps. Sorry if i have messed up the variables, i tried to simplify the code when i added it here and i may have mixed some variables..

Thank you in advance.


回答1:


  1. You could try to generate POCO classes from XML in Visual Studio as it's described here.

  2. You could serialize/deserialize those POCOs using with simple util methods like:

    public static T DeserializeXML<T>(string content)
    {
        if (content == null)
            return default(T);
    
        XmlSerializer xs = new XmlSerializer(typeof(T));
    
        byte[] byteArray = Encoding.ASCII.GetBytes(content);
        var contentStream = new MemoryStream(byteArray);
    
        var xml = xs.Deserialize(contentStream);
    
        return (T)xml;
    }
    
    public static string SerializeAsXML(object item)
    {
        if (item == null)
            return null;
    
        XmlSerializer xs = new XmlSerializer(item.GetType());
    
        using (var sw = new StringWriter())
        {
            using (XmlWriter writer = XmlWriter.Create(sw, new XmlWriterSettings { Indent = true }))
            {
                xs.Serialize(writer, item);
                return sw.ToString();
            }
        }
    }
    
  3. LogRecords probably should be a collection (e.g. an array in this POCO):

        /// <remarks/>
    [System.SerializableAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
    public partial class Log
    {
        /// <remarks/>
        [System.Xml.Serialization.XmlArrayAttribute("LogRecords")]
        [System.Xml.Serialization.XmlArrayItemAttribute("LogRecord", IsNullable = false)]
        public LogRecord[] LogRecords { get; set; }
    }
    

for the next XML format:

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



回答2:


You manually add the root element in the xml. Therefore, you must also manually skip it when reading.

XmlSerializer deserializer = new XmlSerializer(typeof(LogRecord));

using (var xmlReader = XmlReader.Create("LogRecords.xml"))
{
    // Skip root element
    xmlReader.ReadToFollowing("LogRecord");

    LogRecord record = (LogRecord)deserializer.Deserialize(xmlReader);
}

Remove the [XmlRoot("LogRecords")] attribute to make it work.

Of course, you will always get the first element in the xml.


As already suggested in the comments, use the list.

List<LogRecord> logRecords = new List<LogRecord>();

var logRecord = new LogRecord { ... };

// Store each new logRecord to list
logRecords.Add(logRecord);


var serializer = new XmlSerializer(typeof(List<LogRecord>));

// Serialization is done with just a couple lines of code.
using (var fileStream = new FileStream("LogRecords.xml", FileMode.Create))
{
    serializer.Serialize(fileStream, logRecords);
}

// As well as deserialization
using (var fileStream = new FileStream("LogRecords.xml", FileMode.Open))
{
    logRecords = (List<LogRecord>)serializer.Deserialize(fileStream);
}

Thus become unnecessary manipulation using XmlDocument and fuss with manually adding-skipping the root node.



来源:https://stackoverflow.com/questions/47814724/read-xml-element-while-deserializing-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!