读取XML并在C#中创建元素的频率计数

问题描述 投票:1回答:3

我有这种格式的XML文件(但更大):

<customer>
    <name>John</name>
    <age>24</age>
    <gender>M</gender>
</customer>
<customer>
    <name>Keith</name>
    <age></age>         <!--blank value-->
    <gender>M</gender>
</customer>
<customer>
    <name>Jenny</name>
    <age>21</age>
    <gender>F</gender>
</customer>
<customer>
    <name>John</name>   
    <age>24</age>       <!--blank value-->
    <gender>M</gender>  <!--blank value-->
</customer>

我想生成一个数据表,其格式如下:

Element Name Value Frequency名称filled 4 name blank 0年龄filled 2 age blank 2性别填充3性别blank 1

目前,我将分两部分完成此任务,首先如上所述创建一个DataTable结构,并将所有频率默认设置为0。然后使用XmlReader读取XML,并在每次XmlReader找到子元素时增加频率计数。我的问题是,对于具有许多具有许多属性的客户的大型Xml文件,我用于添加实际计数的第二个函数花费的时间太长。如何提高此功能的效率?我的代码:

static void AddCount(DataTable dt)
{
     int count;
     using (XmlReader reader = XmlReader.Create(@"C:\Usr\sample.xml"))
     {
         while (reader.Read())
            {
                if (reader.IsStartElement())
                {
                    string eleName = reader.Name;
                    DataRow[] foundElements = dt.Select("ElementName = '" + eleName + "'");  
                    if (!reader.IsEmptyElement)
                    {
                       count = int.Parse(foundElements.ElementAt(0)["Frequency"].ToString());  
                       foundElements.ElementAt(0).SetField("Frequency", count + 1);
                    }
                    else
                    {
                       count = int.Parse(foundElements.ElementAt(0)["Frequency"].ToString());  
                       foundElements.ElementAt(0).SetField("Frequency", count + 1);
                    }
                }
            }   
       }   
  }    

我也准备将XmlReader类更改为该任务的任何其他更有效的类。欢迎任何建议。

c# xml optimization datatable xmlreader
3个回答
1
投票

您可以使用以下代码:

    using (XDocument xdoc = XDocument.Load(@"C:\Users\aks\Desktop\sample.xml"))
        {
            var customers = xdoc.Descendants("customer");
            var totalNodes = customers.Count();

            var filledNames = customers.Descendants("name").Where(x => x.Value != string.Empty).Count();
            var filledAges = customers.Descendants("age").Where(x => x.Value != string.Empty).Count();
            var filledGenders = customers.Descendants("gender").Where(x => x.Value != string.Empty).Count();

            var unfilledNames = totalNodes - filledNames;
            var unfilledAges = totalNodes - filledAges;
            var unfilledGenders = totalNodes - filledGenders;
        }

1
投票

事实证明,使用Select操作在DataTable中查询非常昂贵,这使我的功能非常慢。

代替它,使用Dictionary<string, ValueFrequencyModel>并对其进行查询以将计数填充到字典中,并在完成后将Dictionary<string, ValueFrequencyModel>转换为数据表。

这为我节省了很多时间并解决了问题。


0
投票

尝试这种逻辑,目前我只在这里使用了一个属性,即名称

        XDocument xl = XDocument.Load(@"C:\Usr\sample.xml");
        var customers = xl.Descendants("Customer");
        var customerCount = customers.Count();
        var filledCustomers = customers.Where(x => x.Element("Name").Value != string.Empty).Count();
        var nonfilledCustomers = customerCount - filledCustomers;
© www.soinside.com 2019 - 2024. All rights reserved.