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.
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:
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;
}
}
}
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
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!!!!!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With