【问题标题】:Is this an inefficient way to parse XML?这是解析 XML 的低效方式吗?
【发布时间】:2010-10-25 15:13:38
【问题描述】:

我可能担心错误的优化,但我有一个唠叨的想法,它一遍又一遍地解析 xml 树,也许我在某个地方读到它。不记得了。

无论如何,这就是我正在做的事情:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.Net;

namespace LinqTestingGrounds
{
    class Program
    {
        static void Main(string[] args)
        {
            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
            webClient.DownloadStringAsync(new Uri("http://www.dreamincode.net/forums/xml.php?showuser=335389"));
            Console.ReadLine();
        }

        static void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                return;
            }

            XDocument xml = XDocument.Parse(e.Result);

            User user = new User();
            user.ID = xml.Element("ipb").Element("profile").Element("id").Value;
            user.Name = xml.Element("ipb").Element("profile").Element("name").Value;
            user.Rating = xml.Element("ipb").Element("profile").Element("rating").Value;
            user.Photo = xml.Element("ipb").Element("profile").Element("photo").Value;
            user.Reputation = xml.Element("ipb").Element("profile").Element("reputation").Value;
            user.Group = xml.Element("ipb").Element("profile").Element("group").Element("span").Value;
            user.Posts = xml.Element("ipb").Element("profile").Element("posts").Value;
            user.PostsPerDay = xml.Element("ipb").Element("profile").Element("postsperday").Value;
            user.JoinDate = xml.Element("ipb").Element("profile").Element("joined").Value;
            user.ProfileViews = xml.Element("ipb").Element("profile").Element("views").Value;
            user.LastActive = xml.Element("ipb").Element("profile").Element("lastactive").Value;
            user.Location = xml.Element("ipb").Element("profile").Element("location").Value;
            user.Title = xml.Element("ipb").Element("profile").Element("title").Value;
            user.Age = xml.Element("ipb").Element("profile").Element("age").Value;
            user.Birthday= xml.Element("ipb").Element("profile").Element("birthday").Value;
            user.Gender = xml.Element("ipb").Element("profile").Element("gender").Element("gender").Element("value").Value;

            Console.WriteLine(user.ID);
            Console.WriteLine(user.Name);
            Console.WriteLine(user.Rating);
            Console.WriteLine(user.Photo);
            Console.WriteLine(user.Reputation);
            Console.WriteLine(user.Group);
            Console.WriteLine(user.Posts);
            Console.WriteLine(user.PostsPerDay);
            Console.WriteLine(user.JoinDate);
            Console.WriteLine(user.ProfileViews);
            Console.WriteLine(user.LastActive);
            Console.WriteLine(user.Location);
            Console.WriteLine(user.Title);
            Console.WriteLine(user.Age);
            Console.WriteLine(user.Birthday);
            Console.WriteLine(user.Gender);

            //Console.WriteLine(xml);            
        }
    }
}

这是 Good Enough™ 还是有更快的方法来解析我需要的东西?

ps。我在 DownloadStringCompleted 事件中执行大部分操作,我不应该这样做吗?第一次使用这种方法。谢谢!

【问题讨论】:

    标签: c# .net xml webclient


    【解决方案1】:

    不知道效率,但为了可读性,请使用profile 变量,而不是一遍又一遍地遍历整个内容:

     User user = new User();
     var profile = xml.Element("ipb").Element("profile");
     user.ID = profile.Element("id").Value;
    

    【讨论】:

    • 啊,是的,将所有配置文件元素分组并使用该 XElement 来解析我需要的内容。那会减少字符数,所以谢谢!
    【解决方案2】:

    我相信 xml 序列化是解决这类问题的方法。只要您的属性与 xml 元素匹配,这将是微不足道的。否则,您只需要使用 XmlElement 和 XmlAttribute 属性类来映射它们。下面是一些将常见的 xml 反序列化为类的简单代码:

    public T Deserialise(string someXml)
        {   
            XmlSerializer reader = new XmlSerializer(typeof (T));
            StringReader stringReader = new StringReader(someXml);
            XmlTextReader xmlReader = new XmlTextReader(stringReader);
            return (T) reader.Deserialize(xmlReader);
        }
    

    【讨论】:

      【解决方案3】:

      我补充了 Oded 的回答: 另一种提高可读性的方法是使用XPathSelectElement 扩展方法。

      所以你的代码看起来像:

      user.ID = xml.XPathSelectElement("ipb/profile/id").Value;
      

      【讨论】:

      • 好主意,但可能更适合遍历集合(即获取节点集进行迭代)而不是这里的特定要求(获取特定节点值)。
      【解决方案4】:

      不,它不是一遍又一遍地解析 XML;只有一次,当你打电话时

      XDocument.Parse(e.Result);
      

      之后的调用只是访问 xml 对象中的树结构。

      “解析”是指分析非结构化文本字符串(例如来自文件)并从中创建数据结构(例如树)。您的... .Element("foo") 调用不是解析而是访问由XDocument.Parse() 调用构建的部分数据结构。

      如果您想知道您的代码是否冗余地重复了某些步骤,并且可以进行优化,那么是的,您正在冗余地遍历 ipb/profile。这不是解析,但对 Element("foo") 的调用确实必须做一些工作,将字符串参数与子元素的名称进行比较。 @Oded 的建议出于可读性原因解决了这个问题,但也有助于提高效率。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-10-08
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-25
        相关资源
        最近更新 更多