tags:

views:

293

answers:

2

Hi,

I am using XmlReader to read an XML File and I want to count XML Element right under of Document Element that as I know it should be the root element.

XML

<?xml version="1.0" encoding="utf-8"?>
<NewsLetters>
  <EMail Date="10/10/2009">[email protected]</EMail>
  <EMail Date="10/10/2009">[email protected]</EMail>
  <EMail Date="10/10/2009">[email protected]</EMail>
  <EMail Date="10/10/2009">[email protected]</EMail>
</NewsLetters>

C# Code :

public static string TotalMemberCount()
{
    XmlTextReader reader = new XmlTextReader(HttpContext.Current.Server.MapPath("~/Newsletter/NewsLetter.xml"));

    int totalCount = 0;
    while (reader.Read())
    {
        if (reader.NodeType == XmlNodeType.Element && reader.NodeType != XmlNodeType.Document)
            totalCount++;
    }

    return totalCount.ToString();
}

Normally I was expecting 4 records but it returns 5 because it also counts the root element. What should I do ? Actually I know how to solve with using XDocument,XElement and LINQ but I want to solve in this way, don't ask me why because I want to learn every way in which I can solve such problems.

Thanks in advance.

Sincerely....

A: 

Anyways, I found my own solution, what I was trying to achieve is to find a generic solution so I came up with such a solution :

XML

<?xml version="1.0" encoding="utf-8"?>
<NewsLetters Root="True">
  <EMail Date="10/10/2009">[email protected]</EMail>
  <EMail Date="10/10/2009">[email protected]</EMail>
  <EMail Date="10/10/2009">[email protected]</EMail>
  <EMail Date="10/10/2009">[email protected]</EMail>
</NewsLetters>

C#

   public static string TotalMemberCount()
    {
        int totalCount = 0;
        using (XmlTextReader reader = new XmlTextReader(HttpContext.Current.Server.MapPath("~/Newsletter/NewsLetter.xml")))
        {
            while (reader.Read())
            {
                if (reader.NodeType != XmlNodeType.XmlDeclaration && reader.NodeType == XmlNodeType.Element)
                {
                    if (reader.MoveToFirstAttribute())
                    {
                        if (reader.Value == "True")
                            //gotcha, I don't want this,this is root element
                            continue;
                    }
                    totalCount++;
                }
            }
            return totalCount.ToString();
        }

    }
Braveyard
+1  A: 

The answer you've come up with is flawed in at least five different ways.

  1. It's certainly not a "generic solution", since your code is now completely dependent on information in the XML - your method can only count elements properly if the XML document it's processing contains the flag attribute that you've added.

  2. The flag attribute's unnecessary. Any time an XmlReader starts at the beginning of the stream it's reading, the first element it reads is always going to be the top-level element. It can't possibly be anything else. Instead of adding an attribute to your document to identify the top-level element, you can just use a flag to track whether or not you've read the top-level element yet. Or heck, you can just subtract 1 from the total.

  3. And even if you did need the flag attribute, you're doing it wrong. You're using MoveToFirstAttribute to find it. What if there's more than one atttribute on the element? What if the first attribute your code finds whose value is True isn't Root? And what if one of the child elements has an attribute on it with that value? If you're going to use an attribute for this purpose, you should, at the very least, search for it by name.

  4. This code won't count all child elements of the top-level element, it will count all descendant elements. The reader moves from node to node in document order. If an element node has a child node, that child node is the next node that gets read by Read(). There are methods of the XmlReader that you can use to read an entire element and all of its content in one single gulp, but you're not using them.

  5. The condition reader.NodeType != XmlNodeType.XmlDeclaration && reader.NodeType == XmlNodeType.Element is redundant: there's no way that a node can be an XML declaration if it's an element.

Robert Rossney
Then what should I do?
Braveyard