C# XML kick in the right direction needed

asked 2021-11-02T01:10:43.117+00:00
Festus Hagen 41 Reputation points

Hi all,

Looking for a kick in the git going in the right direction.

The following C# code is just to show the desired results I would like to implement using XML lookup.

        string Component = ProductComponent(255, 1, 1); // Returns 255:1 Component 1
        string Component = ProductComponent(255, 1, 2); // Returns 255:1 Component 2

        public static string ProductComponent(int product, int component, int index)
        {
            switch (product)
            {
                case 0xFF:
                    switch (component)
                    {
                        case 0x01:
                            switch (index)
                            {
                                case 0x01:
                                    return "255:1 Component 1";
                                case 0x02:
                                    return "255:1 Component 2";
                                case 0x03:
                                    return "255:1 Component 3";
                                case 0x04:
                                    return "255:1 Component 4";
                                case 0x05:
                                    return "255:1 Component 5";
                                default:
                                    return "1 Default";
                            }
                        case 0x02:
                            switch (index)
                            {
                                case 0x01:
                                    return "255:2 Component 1";
                                case 0x02:
                                    return "255:2 Component 2";
                                default:
                                    return "2 Default";
                            }
                        default:
                            return "255 Default";
                    }
                case 0xFE:
                    switch (component)
                    {
                        case 0x01:
                            switch (index)
                            {
                                case 0x01:
                                    return "254:1 Component 1";
                                case 0x02:
                                    return "254:1 Component 2";
                                case 0x03:
                                    return "254:1 Component 3";
                                default:
                                    return "1 Default";
                            }
                        default:
                            return "254 Default";
                    }
                case 0x02:
                    switch (component)
                    {
                        case 0x05:
                            switch (index)
                            {
                                case 0x01:
                                    return "2:5 Component 1";
                                case 0x02:
                                    return "2:5 Component 2";
                                case 0x03:
                                    return "2:5 Component 3";
                                case 0x04:
                                    return "2:5 Component 4";
                                default:
                                    return "5 Default";
                            }
                        default:
                            return "2 Default";
                    }
                default:
                    return "Default";
            }
        }

My thoughts for the XML ... Maybe better idea ??

<?xml version="1.0" encoding="utf-8"?>
<PRODUCTS>
    <PRODUCT id="0xFF">
        <COMPONENTS id="0x01">
            <COMPONENT id="0x01">"255:1 Component 1"</COMPONENT>
            <COMPONENT id="0x02">"255:1 Component 2"</COMPONENT>
            <COMPONENT id="0x03">"255:1 Component 3"</COMPONENT>
            <COMPONENT id="0x04">"255:1 Component 4"</COMPONENT>
            <COMPONENT id="0x05">"255:1 Component 5"</COMPONENT>
        </COMPONENTS>
        <COMPONENTS id="0x02">
            <COMPONENT id="0x01">"255:2 Component 1"</COMPONENT>
            <COMPONENT id="0x02">"255:2 Component 2"</COMPONENT>
        </COMPONENTS>
    </PRODUCT>
    <PRODUCT id="0xFE">
        <COMPONENTS id="0x01">
            <COMPONENT id="0x01">"254:1 Component 1"</COMPONENT>
            <COMPONENT id="0x02">"254:1 Component 2"</COMPONENT>
            <COMPONENT id="0x03">"254:1 Component 3"</COMPONENT>
        </COMPONENTS>
    </PRODUCT>
    <PRODUCT id="0x02">
        <COMPONENTS id="0x05">
            <COMPONENT id="0x00">"2:5 Component 1"</COMPONENT>
            <COMPONENT id="0x01">"2:5 Component 2"</COMPONENT>
            <COMPONENT id="0x02">"2:5 Component 3"</COMPONENT>
            <COMPONENT id="0x03">"2:5 Component 4"</COMPONENT>
        </COMPONENTS>
    </PRODUCT>
</PRODUCTS>

I can do simple XML read into like XDocument, I need more and I'm not sure of a slick classy direction ... Some guidance would be much appreciated!

It is a console app, no gui

Thank you
-Enjoy

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
6,919 questions
No comments
{count} votes

Accepted answer
  1. answered 2021-11-02T06:09:41.383+00:00
    Jack J Jun 19,036 Reputation points Microsoft Employee

    @Festus Hagen , you could try to use XContainer.Descendants Method to use XDocument to get what you want.

    Here is a code example you could refer to.

    static void Main(string[] args)  
            {  
      
                string value1 = ProductComponent(255, 1, 1);  
                string value2 = ProductComponent(255, 1, 2);  
                string value3 = ProductComponent(254, 1, 3);  
                Console.WriteLine(value1);  
                Console.WriteLine(value2);  
                Console.WriteLine(value3)  
      
            }  
      
            public static string ProductComponent(int product, int component, int index)  
            {  
                XDocument doc = XDocument.Load("D:\\test.xml");  
                var result = doc.Descendants("PRODUCT").Where(i => Convert.ToInt32(i.Attribute("id").Value, 16) == product)  
               .Descendants("COMPONENTS").Where(i => Convert.ToInt32(i.Attribute("id").Value, 16) == component).Descendants("COMPONENT").Where(i =>   
                Convert.ToInt32(i.Attribute("id").Value, 16) == index).Select(i => i.Value).FirstOrDefault();  
                return result;  
            }  
    

    Result:

    145695-image.png


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    No comments

3 additional answers

Sort by: Most helpful
  1. answered 2021-11-02T16:08:50.737+00:00
    Festus Hagen 41 Reputation points

    Thank you, thank you very much!

    It is a valid answer, it works, though I was hoping for something a little more classy, I am trying to learn.

    Is the XML structure good for the use ??
    Can it be better ??
    Design is completely open, I wouldn't know good XML from bad XML ATM!

    Can the "id"'s be numeric (remove quotes) to avoid the exception prone Convert.ToInt32(...) ??

    I was thinking of a Products class that loads, parses into a dictionary or, then be able to lookup from the list.
    Been down multiple roads here and have yet to be able to put it all together into a workable solution.

    Like I said, I'm trying to learn something more advanced.

    But I just don't know how to get'er there yet.

    Where I'm at right now is stuck at loading the _products list with class Product keeping everything properly linked.

        public class Product
        {
            public int ProductId { get; }
            public int ComponentID { get; }
            public SortedDictionary<int, string> Components = new SortedDictionary<int, string>();
        }
    
        public class Products
        {
            List<Product> _products;
    
            public Products(string filename)
            {
                _products = new List<Product>();
                LoadProducts(filename);
            }
    
            private void LoadProducts(string filename)
            {
                // Stuck here ATM.
                XDocument doc = XDocument.Load(filename);
            }
        }
    

    Is this a good design/technique ??

    BTW, I am not working in the normal static Program class, I have instantiated my own "Program" class ...

    Thank you!
    -Enjoy

    No comments

  2. answered 2021-11-03T02:40:04.71+00:00
    Jack J Jun 19,036 Reputation points Microsoft Employee

    @Festus Hagen , In my opinion, I suggest that you still use the linq to xml(the first answer) to get the data if you just want to query the data from the xml.

    If you want to load your xml to a class, you could refer to the code example I wrote.

    class Program  
        {  
            static void Main(string[] args)  
            {  
    			string xml = File.ReadAllText("D:\\test.xml");  
                XmlSerializer serializer = new XmlSerializer(typeof(PRODUCTS));  
    			PRODUCTS products = null;  
                using (StringReader reader = new StringReader(xml))  
                {  
                    products = (PRODUCTS)serializer.Deserialize(reader);  
                }  
                foreach (PRODUCT product in products.PRODUCT)  
                {  
                    Console.WriteLine(product.Id);  
    				Console.WriteLine(product.Text);  
                    foreach (COMPONENTS components in product.COMPONENTS)  
                    {  
                        Console.WriteLine(components.Id);  
    					Console.WriteLine(components.Text);  
                        foreach (COMPONENT component in components.COMPONENT)  
                        {  
                            Console.WriteLine(component.Id);  
    						Console.WriteLine(component.Text);  
    					}  
    				}  
      
                    Console.WriteLine("************");  
    			}  
    			string value1= ProductComponent(255, 1, 1);  
    			string value2 = ProductComponent(255, 1, 2);  
    			string value3 = ProductComponent(254, 1, 3);  
                Console.WriteLine(value1);  
    			Console.WriteLine(value2);  
    			Console.WriteLine(value3);  
    			Console.ReadKey();  
            }  
    		static string ProductComponent(int product, int component, int index)  
            {  
    			string xml = File.ReadAllText("D:\\test.xml");  
    			XmlSerializer serializer = new XmlSerializer(typeof(PRODUCTS));  
    			PRODUCTS products = null;  
    			using (StringReader reader = new StringReader(xml))  
    			{  
    				products = (PRODUCTS)serializer.Deserialize(reader);  
    			}  
    			var result = products.PRODUCT.Where(i => Convert.ToInt32(i.Id, 16) == product).Select(i => i.COMPONENTS).FirstOrDefault().Where(i => Convert.ToInt32(i.Id, 16) == component).Select(i => i.COMPONENT).FirstOrDefault().Where(i => Convert.ToInt32(i.Id, 16) == index).Select(i => i.Text).FirstOrDefault();  
    			return result;  
    		}  
    	}  
      
      
    	[XmlRoot(ElementName = "COMPONENT")]  
    	public class COMPONENT  
    	{  
      
    		[XmlAttribute(AttributeName = "id")]  
    		public string Id { get; set; }  
      
    		[XmlText]  
    		public string Text { get; set; }  
    	}  
      
    	[XmlRoot(ElementName = "COMPONENTS")]  
    	public class COMPONENTS  
    	{  
      
    		[XmlElement(ElementName = "COMPONENT")]  
    		public List<COMPONENT> COMPONENT { get; set; }  
      
    		[XmlAttribute(AttributeName = "id")]  
    		public string Id { get; set; }  
      
    		[XmlText]  
    		public string Text { get; set; }  
    	}  
      
    	[XmlRoot(ElementName = "PRODUCT")]  
    	public class PRODUCT  
    	{  
      
    		[XmlElement(ElementName = "COMPONENTS")]  
    		public List<COMPONENTS> COMPONENTS { get; set; }  
      
    		[XmlAttribute(AttributeName = "id")]  
    		public string Id { get; set; }  
      
    		[XmlText]  
    		public string Text { get; set; }  
    	}  
      
    	[XmlRoot(ElementName = "PRODUCTS")]  
    	public class PRODUCTS  
    	{  
      
    		[XmlElement(ElementName = "PRODUCT")]  
    		public List<PRODUCT> PRODUCT { get; set; }  
    	}  
    

    Note: I used Convert.ToInt32 to Convert Byte string to int, there is no exception for me.
    Result:

    145923-image.png


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    No comments

  3. answered 2021-11-09T13:40:04.93+00:00
    Festus Hagen 41 Reputation points

    My goal is to learn not just get it done ...

    I'm not a step one step done toot my horn I got it done kinda guy, I like to take multiple options kneed them twist them and squeeze every bit of understanding out of them I can, then make my decision.

    And if I choose to use XML, I will be using a slightly twisted version of your first suggestion, even though I do not like reading the file every time, however the simplicity ... Gotta love it!

    Thank you!

    No comments