1

I am trying to read in data from an XML file, which I can do with the code below.

How would I then sort the data by name alphabetically to be used on an electronic menu app?

Could someone show me how to do this?

The code block below does work, but I have no idea how to sort the data alphabetically by node type.

For instance, I would like to sort by "name" alphabetically.

Other sorting methods could include sorting by price or category, etc.

Here is the XML data structure:

<?xml version="1.0" encoding="UTF-8" ?>
<base>
    <menu>
        <item>
            <category></category>  
            <name></name>
            <price></price>
            <featured></featured>
            <code></code>
            <timestart></timestart>
            <timeend></timeend>
        </item>
    </menu>
</base>

Here is the code:

public void XML_Get_MenuData()
{
    try
    {
        XmlDocument myDoc2 = new XmlDocument();

        myDoc2.Load("\\user\\today1.xml");

        XmlNodeList itemNodes = myDoc2.GetElementsByTagName("item");

        ushort i = 0;

        Menu_Items = 0;

        foreach (XmlNode sINode in itemNodes)
        {
            Category[i] = sINode["category"].InnerText;
            Console.PrintLine("category: {0}", Category[i]);

            ItemName[i] = sINode["name"].InnerText;
            Console.PrintLine("name: {0}", ItemName[i]);

            Price[i] = sINode["price"].InnerText;
            Console.PrintLine("price: {0}", Price[i]);

            Featured[i] = sINode["featured"].InnerText;
            Console.PrintLine("featured: {0}", Featured[i]);

            if (Featured[i] == "yes")
            {
                uFeatured[i] = 1;
            }
            else
            {
                uFeatured[i] = 0;
            }

            Code[i] = sINode["code"].InnerText;
            Console.PrintLine("code: {0}", Code[i]);


            TimeStart[i] = sINode["timestart"].InnerText;
            Console.PrintLine("timestart: {0}", TimeStart[i]);

            TimeEnd[i] = sINode["timeend"].InnerText;
            Console.PrintLine("timeend: {0}", TimeEnd[i]);

            i++;
        }

        Menu_Items = i;
        Console.PrintLine("Menu Items: {0}", Menu_Items);
    }
    catch
    {
        Console.PrintLine("missed Menu Items: {0}");
    }

}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291

1 Answers1

0

You should look into the lovely LINQ to XML, which allows you to do stuff like this:

var Doc = XDocument.Load("PathToYourXml");

var OrderedItems = Doc.Descendants("item").OrderBy(x => x.Element("name").Value);

OrderedItems contains your objects alphabetically ordered by their name, in the shape of a bunch (bunch = IOrderedEnumerable) of XElements. If you wanted do make the order descending, you'd just use OrderByDescending:

var OrderedItems = Doc.Descendants("item").OrderByDescending(x => x.Element("name").Value);

As a side note, right now you're iterating your items and printing them, and apparently storing the data horizontally in arrays. Mapping them to a class instead would be useful to avoid having to use magical strings like "item" and "name", which is error-prone. I'd encourage you to create a model for your items and investigate a bit on how to parse the XML into a list of your object, using something like an XmlSerializer, and maybe taking a look at questions like this, where you'll find some alternatives.

  • 1
    I agree with you that LINQ is a nice tool for this kind of job. I don't agree with you about binding the data to C# classes. Doing that gives you a big hassle if the format of the data ever changes. – Michael Kay Jun 05 '21 at 07:29
  • It's definitely a trade-off and would depend on the axis of change, but if you want to do stuff like adding prices or sorting by dates, you're gonna have to start making assumptions about the data structure anyways. (Also, I wanted to make the OP check out some potentially new concepts.) – Mariano Luis Villa Jun 05 '21 at 11:42