在反序列化c#时读取xml元素

时间:2017-12-14 13:38:33

标签: c# xml deserialization

我有一个xml文档,其中我以dinamically方式序列化数据,如果我有新请求,则附加新数据。我序列化的对象属性就像这样

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

以这种方式完成序列化:

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

序列化时我使用LogFile.CreateElement("LogRecord"),我的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>

当我尝试像这样反序列化时

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

我为每个属性MessageSender RecipientSendTime的随机值获取空值,我知道这是因为它无法识别XmlElement { {1}}我在序列化时添加了.. 有没有办法读取这个xml元素,所以我可以采取正确的属性值?

聚苯乙烯。对不起,如果我弄乱了变量,我试图简化代码,当我在这里添加它,我可能混合了一些变量..

提前谢谢。

2 个答案:

答案 0 :(得分:0)

  1. 您可以尝试在Visual Studio中从XML生成POCO类,因为它描述了here

  2. 您可以使用简单的util方法序列化/反序列化这些POCO,例如:

    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可能应该是一个集合(例如此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; }
    }
    
  4. 用于下一个XML格式:

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

答案 1 :(得分:0)

您手动在xml中添加根元素。因此,您还必须在阅读时手动跳过它。

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

删除[XmlRoot("LogRecords")]属性以使其正常工作。

当然,您将始终获得xml中的第一个元素。

正如评论中已经建议的那样,使用列表。

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

因此,使用XmlDocument进行不必要的操作,并在手动添加 - 跳过根节点时大惊小怪。