Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to query this two XML files using C#?

Tags:

c#

linq

winforms

I’m creating a small application (a phonebook), actually I already created it using ms access as a database, but now, I’m learning XML and planning to use it as a database for this app (just for fun and educational purposes).

Here’s the diagram in my access database.

alt text

And I created two XML files with the same structure as for the two access tables.

ContactList Table

<?xml version="1.0" standalone="yes"?>
<ContactList>
  <xs:schema id="ContactList" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="ContactList" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Contact">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="ContactID" type="xs:int" minOccurs="0" />
                <xs:element name="Name" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <Contact>
    <ContactID>1</ContactID>
    <Name>Peter</Name>
  </Contact>
  <Contact>
    <ContactID>2</ContactID>
    <Name>John</Name>
  </Contact>
</ContactList>

ContactNumbers Table

<?xml version="1.0" standalone="yes"?>
<ContactNumbers>
  <xs:schema id="ContactNumbers" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="ContactNumbers" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="Numbers">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="ContactID" type="xs:int" minOccurs="0" />
                <xs:element name="Mobile" type="xs:string" minOccurs="0" />
                <xs:element name="Office" type="xs:string" minOccurs="0" />
                <xs:element name="Home" type="xs:string" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <Numbers>
    <ContactID>1</ContactID>
    <Mobile>+63-9277-392607</Mobile>
    <Office>02-890-2345</Office>
    <Home>0</Home>
  </Numbers>
  <Numbers>
    <ContactID>2</ContactID>
    <Mobile>+62-9277-392607</Mobile>
    <Office>02-890-2345</Office>
    <Home>1</Home>
  </Numbers>
</ContactNumbers>

This is how my simple app should look like:

alt text

In my original app, I used INNER JOIN statement to retrieve the contact numbers of a particular contact. But now, I have no idea how to do it since I’m using 2 XML files as the tables (corresponding to the two ms access tables). Is it still possible to query and link these two XML files and achieved the same functionality as my first application (using access) version does?

For now, this is what I only have:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TestXML
{
    public partial class Form1 : Form
    {
        OpenFileDialog openFileDialog1 = new OpenFileDialog();
        DataSet ds = new DataSet();
        DataView dv = new DataView();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            try
            {
                openFileDialog1.Filter = "XML Document (*.xml)|*.xml";
                openFileDialog1.FileName = "";
                openFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    txtDirectory.Text = openFileDialog1.FileName;                    
                    btnLoad.Enabled = true;
                }
            }
            catch (Exception x)
            {
                btnLoad.Enabled = false;
                MessageBox.Show("Something went wrong! \n" + x.Message, "Ooops!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            dgContactList.DataSource = LoadXML();
        }

        private DataView LoadXML()
        {
            try
            {
                ds.Clear();
                ds.ReadXml(txtDirectory.Text, XmlReadMode.ReadSchema);
                dv = ds.Tables[0].DefaultView;
                lblStatus.Text = "XML is loaded successfully";
            }
            catch (Exception x)
            {
                MessageBox.Show("Something went wrong! \n" + x.Message, "Ooops!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                lblStatus.Text = "";
            }
            return dv;
        }
    }
}
like image 418
yonan2236 Avatar asked Nov 15 '22 06:11

yonan2236


1 Answers

Here is my solution(MainList is your 1st XML and DetailedList is the second.)

using System;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Linq;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog OpenFD = new OpenFileDialog();
            OpenFD.InitialDirectory = Application.StartupPath;
            OpenFD.FileName = "";
            OpenFD.ShowDialog();
            if (OpenFD.FileName == "")
                return;
            textBox1.Text = OpenFD.FileName;
            ReadXMLFile(OpenFD.FileName);
        }
        private void ReadXMLFile(String strFileName)
        {
            var X = XDocument.Load(strFileName).Descendants("Contact").Select(N => new
        {
            ID = N.Element("ContactID").Value,
            Name=N.Element("Name").Value 
        });
        foreach (var XX in X)
        {
            dataGridView1.Rows.Add(XX.ID, XX.Name);
        }
    }


    private void dataGridView1_RowHeaderMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        String St = dataGridView1.SelectedRows[0].Cells[0].Value.ToString();
        var Data = XDocument.Load(Application.StartupPath + "\\DetailedList.xml").Descendants("Numbers")
                         .Where(X=>X.Element("ContactID").Value ==St)
                         .Select(N => new
                          {
                              Mobile = N.Element("Mobile").Value,
                              Office = N.Element("Office").Value,
                              Home = N.Element("Home").Value
                          });
        dataGridView2.Rows.Clear();
        foreach (var X in Data)
        {
            dataGridView2.Rows.Add(X.Mobile,X.Office,X.Home);
        }
    }
}
}

Output

Result

Add the necessary property to both the gridViews

I've created the columns at the design time.

And Instead of foreach we can wse LAMBDA Expression Hope you will understand.... Please let me know if you have any isses.

Enjoy!!!!!

like image 132
Thorin Oakenshield Avatar answered Dec 21 '22 00:12

Thorin Oakenshield