Read a part of XML file into a table

Raymond Gilbers 176 Reputation points
2022-06-21T19:46:05.967+00:00

Hello All,

I'm able to read specific data from a XML file. But the way the file is set up and how I would like my program works I need to create (I think) something like a datatable or so. Unfortunately i'm not sure how to tackle this issue.

The XML file looks like this:

<Root>  
  <CompanyProfile>  
    <CompanyName>Raymond</CompanyName>  
    <SiteName>Gilbers</SiteName>  
    <Imo>123654</Imo>  
    <MachineTotal>2</MachineTotal>  
  </CompanyProfile>  
  <MachineProfile>  
    <MachineName>mach1</MachineName>  
    <SerialNumber>123987</SerialNumber>  
    <TypeNumber>AMI500</TypeNumber>  
    <Type>AC</Type>  
    <NominalSpeed>3000</NominalSpeed>  
    <Frequency>50</Frequency>  
    <NominalPower>1500</NominalPower>  
  </MachineProfile>  
  <MachineProfile>  
    <MachineName>Mach2</MachineName>  
    <SerialNumber>987654</SerialNumber>  
    <TypeNumber>AMZ500</TypeNumber>  
    <Type>AC</Type>  
    <NominalSpeed>1500</NominalSpeed>  
    <Frequency>50</Frequency>  
    <NominalPower>1700</NominalPower>  
  </MachineProfile>  
</Root>  
  

what I want is to read the machineprofile. And "connect" the machinename to a combobox. So in other words I want the combobox has the items mach 1, mach2 mach3 etc and when I selet a particular selection all specific items whith this machine will be displayed.
I'm able to read the XML that is not the issue I guess but I don't know how to tackle the next issue....do I need to make a new method or create a DataTable or so. I know how machine "Machines exsist" so I thought I create a kind of loop and place it in a method but that will not work I really think I have to place each data in a table. And the selection should have some kind of identity (e.g a number) which shows me later on all the info I want to see.

How can I do this?

private void openToolStripMenuItem_Click(object sender, EventArgs e)       
        {  
            using (OpenFileDialog ofd = new OpenFileDialog())  
            {  
                ofd.Filter =  "XML File (*.xml)|*.xml";  
                ofd.Title = "Open Client Profile File";  
  
                if (ofd.ShowDialog() == DialogResult.OK)  
                {  
                    //Deserialize  
                    _root = HelperXml.DeserializeXMLFileToObject<XmlRoot>(ofd.FileName);  
  
                    lblCompanyName.Text = _root.CompanyProfile.CompanyName;  
                    lblSiteName.Text = _root.CompanyProfile.SiteName;  
                    lblImo.Text = _root.CompanyProfile.Imo.ToString();  
                    lblMachineTotal.Text = _root.CompanyProfile.MachineTotal.ToString();  
                    lblClientNumber.Text = _root.CompanyProfile.ClientNumber.ToString();  
  
  
                    //Parse machine total to a machine total number.  
                    int counter = Int32.Parse(lblMachineTotal.Text);  
   
                }  
            }  
        }  

All the previous lables I'm able to read correctly but as you can see the Mach1 till 3 I would like to make vissible with selecting a selection in a combobox:

213498-image.png

This combobox e.g. the top left one should show mach 1, mach 2 etc en selecting a particular one it should show all its relevant info. What should I do?

Maybe someone could give me some ideas.

Thanks in advance!

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.
9,936 questions
0 comments No comments
{count} votes

Accepted answer
  1. Karen Payne MVP 35,011 Reputation points
    2022-06-21T21:21:30.32+00:00

    Unsure if this is what you are after. I setup a ComboBox DataSource to RootMachineProfile as a list. This means you have access to each property that can be data bound to controls. Classes were generated by Visual Studio paste special.

    For the ComboBox, no need to set DisplayMember.

    public class XmlOperations  
    {  
        public static Root Read()  
        {  
            const string fileName = @"XMLFile1.xml";  
            var xmlSerializer = new XmlSerializer(typeof(Root), new XmlRootAttribute { ElementName = "Root", IsNullable = true });  
            using (var fs = new FileStream(fileName, FileMode.Open))  
            {  
                return (Root)xmlSerializer.Deserialize(fs);  
                  
            }  
        }  
    }  
      
    [SerializableAttribute()]  
    [System.ComponentModel.DesignerCategoryAttribute("code")]  
    [XmlTypeAttribute(AnonymousType = true)]  
    [XmlRootAttribute(Namespace = "", IsNullable = false)]  
    public partial class Root  
    {  
      
        private RootCompanyProfile companyProfileField;  
        private RootMachineProfile[] machineProfileField;  
      
        public RootCompanyProfile CompanyProfile  
        {  
            get => companyProfileField;  
            set => companyProfileField = value;  
        }  
        [XmlElementAttribute("MachineProfile")]  
        public RootMachineProfile[] MachineProfile  
        {  
            get => machineProfileField;  
            set => machineProfileField = value;  
        }  
      
        public override string ToString() => $"{CompanyProfile.CompanyName}";  
    }  
      
    /// <remarks/>  
    [SerializableAttribute()]  
    [System.ComponentModel.DesignerCategoryAttribute("code")]  
    [XmlTypeAttribute(AnonymousType = true)]  
    public partial class RootCompanyProfile  
    {  
      
        private string companyNameField;  
        private string siteNameField;  
        private uint imoField;  
        private int machineTotalField;  
      
        public string CompanyName  
        {  
            get => companyNameField;  
            set => companyNameField = value;  
        }  
        public string SiteName  
        {  
            get => siteNameField;  
            set => siteNameField = value;  
        }  
        public uint Imo  
        {  
            get => imoField;  
            set => imoField = value;  
        }  
        public int MachineTotal  
        {  
            get => machineTotalField;  
            set => machineTotalField = value;  
        }  
    }  
      
      
    [SerializableAttribute()]  
    [System.ComponentModel.DesignerCategoryAttribute("code")]  
    [XmlTypeAttribute(AnonymousType = true)]  
    public partial class RootMachineProfile  
    {  
      
        private string machineNameField;  
        private uint serialNumberField;  
        private string typeNumberField;  
        private string typeField;  
        private ushort nominalSpeedField;  
        private byte frequencyField;  
        private ushort nominalPowerField;  
      
        public string MachineName  
        {  
            get => machineNameField;  
            set => machineNameField = value;  
        }  
      
        public uint SerialNumber  
        {  
            get => serialNumberField;  
            set => serialNumberField = value;  
        }  
        public string TypeNumber  
        {  
            get => typeNumberField;  
            set => typeNumberField = value;  
        }  
        public string Type  
        {  
            get => typeField;  
            set => typeField = value;  
        }  
        public ushort NominalSpeed  
        {  
            get => nominalSpeedField;  
            set => nominalSpeedField = value;  
        }  
        public byte Frequency  
        {  
            get => frequencyField;  
            set => frequencyField = value;  
        }  
        public ushort NominalPower  
        {  
            get => nominalPowerField;  
            set => nominalPowerField = value;  
        }  
        public override string ToString() => MachineName;  
    }  
    

    Form code

    var result = XmlOperations.Read();  
    List<RootMachineProfile> dataSource = result.MachineProfile.ToList();  
    comboBox1.DataSource = dataSource;  
    
    0 comments No comments

4 additional answers

Sort by: Most helpful
  1. Raymond Gilbers 176 Reputation points
    2022-06-21T21:37:13.83+00:00

    Thank you very much for the detaild answer but (with all due respect) I hate copy paste I want to learn something from it. And i do not see what you have done that is not your fault but my lack of understanding C#

    You created a new Class ok.....untill that I understand but than i basically get lost but again thats probably my errror I appreciate a bit more help for the sake of learning


  2. Raymond Gilbers 176 Reputation points
    2022-06-22T06:52:55.463+00:00

    Thanks for all the great answers I will study the example code hat will help me

    0 comments No comments

  3. Raymond Gilbers 176 Reputation points
    2022-06-22T08:48:40.523+00:00

    I think I'm almost there but I don't understand one thing. The combobox get filled with different info as I expected and as the above example.

     //Deserialize  
                        _root = HelperXml.DeserializeXMLFileToObject<XmlRoot>(ofd.FileName);  
    
                        lblCompanyName.ForeColor = Color.Black;  
                        lblCompanyName.Text = "Company Name: " + _root.CompanyProfile.CompanyName;  
                        lblSiteName.Text ="Sitename: " + _root.CompanyProfile.SiteName;  
                        lblImo.Text = "IMO: " + _root.CompanyProfile.Imo.ToString();  
                        lblMachineTotal.Text = "Machine Total: " + _root.CompanyProfile.MachineTotal.ToString();  
                        lblClientNumber.Text = "Clientnumber: " + _root.CompanyProfile.ClientNumber.ToString();  
    
    
                        _bindingSource.DataSource = _root.MachineProfiles.ToList();  
                        cmbMachineName.DataSource = _bindingSource;  
                        lblPower.DataBindings.Add("Text", _bindingSource, nameof(MachineProfile.NominalPower));  
    

    This is how I have done it. I created a list of the MachineProfiles and added that to the combobox. The result is what you see in below picture I dont understand why and what I do wrong.

    ![![![![213740-image.png]2]1]1]1

    With debugging I can see that the databinding from the list worked out well (I guess)

    213791-image.png

    So I'm a bit confused cause I think I did exactly as @Karen Payne MVP suggested. Does anybody see where I go wrong?


  4. Jack J Jun 24,266 Reputation points Microsoft Vendor
    2022-06-23T06:06:23.88+00:00

    @Raymond Gilbers ,Welcome to Microsoft Q&A, I used a new method to show the related information in the form.

    First, I used the following code to convert the xml file to the datatable by using linq to xml.

     public DataTable GetDataTable(string file)  
            {  
                DataTable dt = new DataTable();  
                XDocument doc = XDocument.Load(file);  
                dt.Columns.Add("Imo");  
                dt.Columns.Add("MachineTotal");  
                dt.Columns.Add("MachineName");  
                dt.Columns.Add("Type");  
                dt.Columns.Add("NominalSpeed");  
                dt.Columns.Add("Frequency");  
                dt.Columns.Add("NominalPower");  
      
                string[] arr = new string[7];  
      
                var result = doc.Descendants("CompanyProfile").First();  
                Console.WriteLine(result.Element("Imo").Value);  
                Console.WriteLine(result.Element("MachineTotal").Value);  
                var dr = from n in doc.Descendants("MachineProfile")  
                         select new string[]{  
                         arr[0] = result.Element("Imo").Value,  
                         arr[1] = result.Element("MachineTotal").Value,  
                         arr[2] = n.Element("MachineName").Value,  
                         arr[3] = n.Element("Type").Value,  
                         arr[4] = n.Element("NominalSpeed").Value,  
                         arr[5] = n.Element("Frequency").Value,  
                         arr[6] = n.Element("NominalPower").Value,  
      
                     };  
      
                foreach (var item in dr)  
                {  
                    dt.Rows.Add(item[0], item[1], item[2], item[3], item[4], item[5], item[6]);  
                }  
                return dt;  
            }  
    

    Second, we could use combobox_SelectedValueChanged event to load the related information from the selected item.

     private void MachineNamecmb_SelectedValueChanged(object sender, EventArgs e)  
            {  
                DataRow row = dt.Rows.Cast<DataRow>().Where(i => i.Field<string>("MachineName") == MachineNamecmb.SelectedItem.ToString()).First();  
                int index = dt.Rows.IndexOf(row);  
                txtImo.Text = dt.Rows[index]["Imo"].ToString();  
                txtFrequency.Text = dt.Rows[index]["Frequency"].ToString();  
                txtMachineTotal.Text= dt.Rows[index]["MachineTotal"].ToString();   
                txtType.Text= dt.Rows[index]["Type"].ToString();  
                txtNominalPower.Text= dt.Rows[index]["NominalPower"].ToString();  
                txtSpeed.Text = dt.Rows[index]["NominalSpeed"].ToString();  
      
            }  
    

    Third, Please use the following code to load the MachineName to the combobox in the button_click event.

    214085-image.png

    Result:

    214174-1.gif

    Best regards,
    Jack


    If the answer is the right solution, please click "Accept Answer" and 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.

    0 comments No comments