Search code examples
c#xmlparsingxmlreader

parsing XML Data using c#


I have been struggling with the XMLReaderClass in c# for some time now and just can't seem to get the concept. Basically I want to loop through the XML File and if the category in the xml doc is the same as the category I have passed it in, I want to add its name to a List.

here is the xml

<?xml version="1.0" encoding="utf-8" ?>
<!-- Do not modify this xml file. -->
<Products>
    <product category="Food"  name="Baking potatoes" />
    <product category="Food" name="Chicken fillet" />
    <product category="Food" name="Chocolate gateau" />
    <product category="Food" name="Madras curry sauce" />
    <product category="Food" name="Organic carrots" />
    <product category="Food" name="Semi-skimmed milk" />
    <product category="Home" name="Washing powder" />
    <product category="Home" name="Rubber gloves" />
    <product category="Home" name="Spray wax" />
    <product category="Home" name="Dish soap" />
    <product category="Pet" name="Cat food" />
    <product category="Pet" name="Dog food" />
    <product category="Pet" name="Collar" />
    <product category="Pet" name="Leash" />
</Products>

and here is my code I have started to work on but didn't get very far :(

public ReadOnlyCollection<string> GetProductsByCategory(string category)
    {
        List<string> returnList = new List<string>();

        using (XmlReader productsReader = GetProductsReader())
        {


            productsReader.MoveToContent();
            while (productsReader.Read())

                if(productsReader.NodeType == XmlNodeType.Element)
            {
                if (productsReader)
                {
                    if productsReader
                }
            }

        }

        return new ReadOnlyCollection<string>(returnList);
    }

Solution

  • Using an XmlReader here will just be a pain to use. Use LINQ to XML here using that API instead, it will make your life easier.

    public static ReadOnlyCollection<string> GetProductsByCategory(string category)
    {
        using (var reader = GetProductsReader())
        {
            var doc = XDocument.Load(reader);
            var results = doc.Element("Products")
                .Elements("product")
                .Where(e => (string)e.Attribute("category") == category)
                .Select(e => (string)e.Attribute("name"))
                .ToList();
            return new ReadOnlyCollection<string>(results);
        }
    }
    

    If for whatever reason you still wish to use the XmlReader, you could read it like this:

    public static ReadOnlyCollection<string> GetProductsByCategory(string category)
    {
        var results = new List<string>();
        var settings = new XmlReaderSettings
        {
            IgnoreWhitespace = true,
            IgnoreComments = true,
        };
        using (var reader = XmlReader.Create(GetProductsReader(), settings))
        {
            reader.MoveToContent();
            reader.ReadStartElement("Products");
            do
            {
                if (reader.IsStartElement("product"))
                {
                    if (reader.MoveToFirstAttribute())
                    {
                        string currentCategory = null;
                        string currentName = null;
                        do
                        {
                            switch (reader.Name)
                            {
                            case "category":
                                currentCategory = reader.ReadContentAsString();
                                break;
                            case "name":
                                currentName = reader.ReadContentAsString();
                                break;
                            }
                        } while (reader.MoveToNextAttribute());
                        if (currentCategory == category && currentName != null)
                            results.Add(currentName);
                    }
                }
            } while (reader.ReadToNextSibling("product"));
        }
        return new ReadOnlyCollection<string>(results);
    }