从XML读取数据集c#

时间:2013-05-09 13:59:01

标签: c# xml visual-studio-2010 linq-to-xml

我正在设计一个简单的课程,用于在托管网站上记录消息。

为了存储消息,我创建了这个简单的类结构:

public class StoredMsg {
  public StoredMsg() {
  }
  public string From { get; set; }
  public string Date { get; set; }
  public string Message { get; set; }
}

将使用StoredMessages : List<StoredMsg>类编写和回读这些消息。

这是Read方法的原始格式:

  public void Read() {
    //string xmlPath = WebPage.Server.MapPath(XML_PATH);
    if (File.Exists(xmlPath)) {
      using (var xr = new XmlTextReader(xmlPath)) {
        StoredMsg item = null;
        while (xr.Read()) {
          if (xr.NodeType == XmlNodeType.Element) {
            if (xr.Name == HEAD) {
              if (item != null) {
                this.Add(item);
              }
              item = new StoredMsg();
            } else if (xr.Name == FROM) {
              item.From = xr.ReadElementString();
            } else if (xr.Name == DATE) {
              item.Date = xr.ReadElementString();
            } else if (xr.Name == MESSAGE) {
              item.Message = xr.ReadElementString();
            }
          }
        }
        xr.Close();
      }
    }
  }

Write方法最初采用以下格式:

  public void Write(StoredMsg item) {
    using (var stream = File.Open(xmlPath, FileMode.Append, FileAccess.Write, FileShare.Read)) {
      using (var xw = new System.Xml.XmlTextWriter(stream, Encoding.UTF8)) {
        xw.WriteStartElement(HEAD);
        {
          xw.WriteWhitespace("\r\n\t");
          xw.WriteElementString(FROM, item.From);
          xw.WriteWhitespace("\r\n\t");
          xw.WriteElementString(DATE, item.Date);
          xw.WriteWhitespace("\r\n\t");
          xw.WriteElementString(MESSAGE, item.Message);
          xw.WriteWhitespace("\r\n");
        }
        xw.WriteEndElement();
        xw.WriteWhitespace("\r\n");
      }
      stream.Close();
    }
  }

问题是Read方法不喜欢XML结构中的内容,所以我的列表总是空的。

在托管网站上很难解决这个问题,因此我开始在网上查看示例,看看我可能做错了什么。

在我搜索过程中,我发现Microsoft's How to: Write Object Data to an XML File (C# and Visual Basic)向我展示了简化Write方法的简化方法:

private XmlSerializer serializer;

public StoredMessages() {
  serializer = new XmlSerializer(typeof(StoredMsg));
}

public void Write(StoredMsg item) {
  using (var file = new StreamWriter(xmlPath, true)) {
    serializer.Serialize(file, item);
  }
}

对我而言,简单而优雅!

对此感到高兴,我继续Microsoft's How to: Read Object Data from an XML File (C# and Visual Basic),所以我也可以实现它。

问题在于:

我能做的最好的事情就是写下我的方法:

public void Read() {
  if (File.Exists(xmlPath)) {
    using (var file = new StreamReader(xmlPath)) {
      // How do I handle multiple nodes?
      // http://msdn.microsoft.com/en-us/library/vstudio/ms172872.aspx
      var item = (StoredMsg)serializer.Deserialize(file);
      this.Add(item);
    }
  }
}

我非常有兴趣看到有人告诉我如何阅读Linq to XML中的所有项目,我会给出+1,但这里的问题是我将如何阅读所有使用此数据的数据{ {1}}以上技术。

我是否错误地将反序列化对象转换为Read而不是其他内容?如果是这样,其他东西会是什么?

  • StoredMsg
  • StoredMsg[]
  • List<object>

感谢阅读所有这些,我希望我的代码对其他人也清晰可见。

作为屏幕截图提供的示例数据,以防止其他人轻易抓取我的电子邮件地址:

Screenshot

2 个答案:

答案 0 :(得分:1)

这是更通用的方法,不,你可以将任何对象传递给读/写

void Write<T>(Stream s,T obj)
{
    var serializer = new XmlSerializer(typeof(T));
    serializer.Serialize(s, obj);
}

T Read<T>(Stream s)
{
    var serializer = new XmlSerializer(typeof(T));
    return (T)serializer.Deserialize(s);
}

例如

StoredMsg[] msgs = .....;
Write(stream, msgs);

StoredMsg[] msgs = Read<StoredMsg[]>(stream());

修改

void Write<T>(string fileName, T obj)
{
    using (var stream = File.Create(fileName))
    {
        Write(stream, obj);
    }
}

T Read<T>(string fileName)
{
    using (var stream = File.Open(fileName, FileMode.Open))
    {
        return Read<T>(stream);
    }
}

答案 1 :(得分:1)

假设有类似的XML结构:

<Messages>
  <MessageHead>
    <From>Stackoverflow</From>
    <Date>09/05/2013</Date>
    <Message>Hello world</Message>
  </MessageHead>
  <MessageHead>
    <From>Stackoverflow</From>
    <Date>09/05/2013</Date>
    <Message>Second Message</Message>
  </MessageHead>
</Messages>

您可以使用LINQ to XML查询将每个MessageHead子节点作为单个消息读取:

var nodes = (from n in xml.Descendants("MessageHead")
             select new
             {
                 From = (string)n.Element("From").Value,
                 Date = (string)n.Element("Date").Value,
                 Message = (string)n.Element("Message").Value
             }).ToList();

这给出了包含以下两个节点的列表:

  • 日期
  • 消息

从那里可以很容易地将它们映射到你的班级,例如

foreach (var n in nodes)
{
     StoredMessage s = new StoredMessage();
     s.from = n.From;
     s.date = n.Date;
     s.message = n.Message;
}