XML序列化List<T> - XML根

13

这是来自 Stack Overflow (.Net 2.0) 的第一个问题:

我正在尝试返回一个包含以下内容的 List 的 XML :

public XmlDocument GetEntityXml()
    {        
        StringWriter stringWriter = new StringWriter();
        XmlDocument xmlDoc = new XmlDocument();            

        XmlTextWriter xmlWriter = new XmlTextWriter(stringWriter);

        XmlSerializer serializer = new XmlSerializer(typeof(List<T>));

        List<T> parameters = GetAll();

        serializer.Serialize(xmlWriter, parameters);

        string xmlResult = stringWriter.ToString();

        xmlDoc.LoadXml(xmlResult);

        return xmlDoc;
    }

现在我已经定义了多个实体,将会使用这个。

假设我想要获取一个 List<Cat> 的 XML。

XML 会是这样的:

<ArrayOfCat>
  <Cat>
    <Name>Tom</Name>
    <Age>2</Age>
  </Cat>
  <Cat>
    <Name>Bob</Name>
    <Age>3</Age>
  </Cat>
</ArrayOfCat>

获取这些实体时,是否有一种方法可以始终获得相同的根实体?

示例:

<Entity>
  <Cat>
    <Name>Tom</Name>
    <Age>2</Age>
  </Cat>
  <Cat>
    <Name>Bob</Name>
    <Age>3</Age>
  </Cat>
</Entity>

还要注意的是,我不打算将XML反序列化回List<Cat>


“始终获得相同的根”是什么意思?请提供更多细节… - Thomas Levesque
4个回答

31

有一个更简单的方法:

public XmlDocument GetEntityXml<T>()
{
    XmlDocument xmlDoc = new XmlDocument();
    XPathNavigator nav = xmlDoc.CreateNavigator();
    using (XmlWriter writer = nav.AppendChild())
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<T>), new XmlRootAttribute("TheRootElementName"));
        ser.Serialize(writer, parameters);
    }
    return xmlDoc;
}

采用这种方法,必须静态缓存并重复使用 XmlSerializer 以避免严重的内存泄漏问题,请参阅 Memory Leak using StreamReader and XmlSerializer 了解详细信息。 - dbc

8

如果我理解正确,您希望文档的根始终相同,无论集合中的元素类型如何?在这种情况下,您可以使用XmlAttributeOverrides:

       XmlAttributeOverrides overrides = new XmlAttributeOverrides();
       XmlAttributes attr = new XmlAttributes();
       attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
       overrides.Add(typeof(List<T>), attr);
       XmlSerializer serializer = new XmlSerializer(typeof(List<T>), overrides);
       List<T> parameters = GetAll();
       serializer.Serialize(xmlWriter, parameters);

6
同样的事情更好的方法:
public XmlDocument GetEntityXml<T>()
{
    XmlAttributeOverrides overrides = new XmlAttributeOverrides();
    XmlAttributes attr = new XmlAttributes();
    attr.XmlRoot = new XmlRootAttribute("TheRootElementName");
    overrides.Add(typeof(List<T>), attr);

    XmlDocument xmlDoc = new XmlDocument();
    XPathNavigator nav = xmlDoc.CreateNavigator();
    using (XmlWriter writer = nav.AppendChild())
    {
        XmlSerializer ser = new XmlSerializer(typeof(List<T>), overrides);
        List<T> parameters = GetAll<T>();
        ser.Serialize(writer, parameters);
    }
    return xmlDoc;
}

最重要的是它可以直接序列化为XmlDocument。您的代码需要解析结果以便将其放回文档中。您的代码还使用了大量过时的XmlTextWriter。 - John Saunders
这真的很有帮助,但由于我正在使用无法序列化的字典,这篇文章对我帮助很大:http://theburningmonk.com/2010/05/net-tips-xml-serialize-or-deserialize-dictionary-in-csharp/comment-page-1/#comment-3697 - Mike Malter

2
如此简单....
public static XElement ToXML<T>(this IList<T> lstToConvert, Func<T, bool> filter, string rootName)
{
    var lstConvert = (filter == null) ? lstToConvert : lstToConvert.Where(filter);
    return new XElement(rootName,
       (from node in lstConvert
       select new XElement(typeof(T).ToString(),
       from subnode in node.GetType().GetProperties()
       select new XElement(subnode.Name, subnode.GetValue(node, null)))));

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接