是否有更简单的方法来反序列化类似的XML文件?

时间:2009-11-24 21:44:46

标签: c# xml xml-serialization

我正在编写一个类库,它抽象出网站上XML文件中包含的数据。每个XML文件使用相同的根元素:pagepage的后代取决于我正在下载的特定文件。例如:

<!-- http://.../groups.xml -->
<page url="/groups.xml">
  <groups>
    <group id="1" >
      <members>
        <member name="Adrian" />
        <member name="Sophie" />
        <member name="Roger" />
      </members>
    </group>
  </groups>
</page>

<!-- http://.../project.xml?n=World%20Domination -->
<page url="/project.xml">
  <projectInfo>
    <summary classified="true" deadline="soon" />
    <team>
      <member name="Pat" />
      <member name="George" />
    </team>
  </projectInfo>
</page>

最后还有一些我想要下载和处理的XML文件。出于这个原因,我一直试图想出一个很好的,干净的方法来反序列化数据。我尝试了一些方法,但是当我回顾我的代码时,每种方法都让我觉得有点脏。我最新的化身使用以下方法:

internal class Provider
{
    /// <summary>Download information from the host.</summary>
    /// <typeparam name="T">The type of data being downloaded.</typeparam>
    internal T Download<T>(string url) where T : IXmlSerializable, new()
    {
        try
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            var response = (HttpWebResponse)request.GetResponse();
            using (var reader = XmlReader.Create(response.GetResponseStream()))
            {
                // Skip the XML prolog (declaration and stylesheet reference).
                reader.MoveToContent();

                // Skip the `page` element.
                if (reader.LocalName == "page") reader.ReadStartElement();

                var serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(reader);
            }
        }
        catch (WebException ex) { /* The tubes are clogged. */ }
    }
}

[XmlRoot(TypeName = "groups")]
public class GroupList : List<Group>, IXmlSerializable
{
    private List<Group> _list;

    public void ReadXml(XmlReader reader)
    {
        if (_list == null) _list = new List<Group>();

        reader.ReadToDescendant("group");

        do
        {
            var id = (int)reader["id"];
            var group = new Group(id);

            if (reader.ReadToDescendant("member"))
            {
                do
                {
                    var member = new Member(reader["name"], group);
                    group.Add(member);
                } while (reader.ReadToNextSibling("member"));
            }

            _list.Add(group);
        } while (reader.ReadToNextSibling("group"));

        reader.Read();
    }
}

这有效,但我觉得有一种更好的方式,我没有看到。我在启动这个项目时尝试使用xsd.exe实用程序。虽然它可以最大限度地减少我编写的代码量,但它并不是理想的解决方案。这将是我现在使用的相同方法 - 我会更快地到达那里。我正在寻找更好的解决方案。所有页面都有page元素的共同点 - 是不是有办法利用它?是否可以拥有一个可序列化的容器类Page,它可能包含其他对象的组合,具体取决于下载的文件?有没有更简单的方法来实现这个目标?

1 个答案:

答案 0 :(得分:5)

.NET在命令行上提供了“xsd.exe”实用程序。

在原始xml文件上运行xsd.exe (xmlfilename),它将从XML数据文件中派生出XML架构(xsd)。

运行xsd.exe (xsd file name) /C,它将创建一个C#类,可用于将这样的XML文件反序列化为C#类。

当然,由于它只有一个XML文件可供使用,因此xsd.exe在其衍生的XML模式中并不完美 - 但这可能是您开始使用的快捷方式。< / p>