 |
Maintenance of XML Elements |
|
|
|
In some cases, you may want to perform an operation on
an existing and particular node. For example, you may want to change the value
of a node, you may want to add a new child node to an existing node, etc. Before
taking any of these actions, you must be able to locate or identify the desired
element.
|
|
Locating an element consists of looking for a particular
node among the nodes. To do this, you must start somewhere. Obviously, the first
node you can identify is the root. Once you get the root, you can then get a
collection of its children. After getting a collection of the children of the
root, you can locate a node in the collection. If the node you are looking for
is a child of that first collection, you can then get a collection of the child
nodes of that node and proceed.
Fortunately, the System.Xml namespace provides
various means of looking for a node in an XML file.
|
|
|
Practical
Learning: Introducing Element Location
|
|
- Start Microsoft Visual C#
- Create a Windows
Application named GeorgetownDryCleaner4
- In the Solution Explorer, right-click Form1.cs and click Rename
- Type Central.cs and press Enter
- Design the form as follows:
 |
| Control |
Name |
Text |
Additional Properties |
| GroupBox |
 |
|
Order Identification |
|
| Label |
 |
|
&Receipt #: |
|
| TextBox |
 |
txtReceiptNumber |
1000 |
TextAlign: Right |
| Button |
 |
btnOpen |
Open |
|
| Button |
 |
btnNewCleaningOrder |
New Cleaning Order |
|
| Label |
 |
|
Customer Name: |
|
| TextBox |
 |
txtCustomerName |
|
|
| Label |
 |
|
Customer Phone: |
|
| MaskedTextBox |
 |
txtCustomerPhone |
|
Mask: (999) 000-0000 |
| Label |
 |
|
Date Left: |
|
| DateTimePicker |
 |
dtpDateLeft |
|
|
| Label |
 |
|
Time Left: |
|
| DateTimePicker |
 |
dtpTimeLeft |
|
Format: Time |
| Label |
 |
|
Date Expected: |
|
| DateTimePicker |
 |
dtpDateExpected |
|
|
| Label |
 |
|
Time Expected: |
|
| DateTimePicker |
 |
dtpTimeExpected |
|
Format: Time |
| Label |
 |
|
Order &Status: |
|
| ComboBox |
 |
cbxOrderStatus |
|
|
| Label |
 |
|
D&ate Picked Up: |
|
| DateTimePicker |
 |
dtpDatePickedUp |
|
|
| Label |
 |
|
Time Pic&kep Up: |
|
| DateTimePicker |
 |
dtpTimePickedUp |
|
|
| GroupBox |
 |
|
Order Processing |
|
| Label |
 |
|
Item Type |
|
| Label |
 |
|
Unit Price |
|
| Label |
 |
|
Qty |
|
| Label |
 |
|
Sub Total |
|
| Label |
 |
|
Shirts |
|
| TextBox |
 |
txtShirtsUnitPrice |
1.25 |
TextAlign: Right |
| TextBox |
 |
txtShirtsQuantity |
0 |
TextAlign: Right |
| TextBox |
 |
txtShirtsSubTotal |
0.00 |
TextAlign: Right |
| Label |
 |
|
Pants |
|
| TextBox |
 |
txtPantsUnitPrice |
1.95 |
TextAlign: Right |
| TextBox |
 |
txtPantsQuantity |
|
TextAlign: Right |
| TextBox |
 |
txtPantsSubTotal |
0.00 |
TextAlign: Right |
| ComboBox |
 |
cbxItem1Name |
None |
Items:
None
Women Suit
Dress
Regular Skirt
Skirt With Hook
Men's Suit 2Pc
Men's Suit 3Pc
Sweaters
Silk Shirt
Tie
Coat
Jacket
Swede |
| TextBox |
 |
txtItem1UnitPrice |
0.00 |
TextAlign: Right |
| TextBox |
 |
txtItem1Quantity |
0 |
TextAlign: Right |
| TextBox |
 |
txtItem1SubTotal |
0.00 |
TextAlign: Right |
| ComboBox |
 |
cbxItem2Name |
None |
Items:
None
Women Suit
Dress
Regular Skirt
Skirt With Hook
Men's Suit 2Pc
Men's Suit 3Pc
Sweaters
Silk Shirt
Tie
Coat
Jacket
Swede |
| TextBox |
 |
txtItem2UnitPrice |
0.00 |
TextAlign: Right |
| TextBox |
 |
txtItem2Quantity |
0 |
TextAlign: Right |
| TextBox |
 |
txtItem2SubTotal |
0.00 |
TextAlign: Right |
| ComboBox |
 |
cbxItem3Name |
None |
Items:
None
Women Suit
Dress
Regular Skirt
Skirt With Hook
Men's Suit 2Pc
Men's Suit 3Pc
Sweaters
Silk Shirt
Tie
Coat
Jacket
Swede |
| TextBox |
 |
txtItem3UnitPrice |
0.00 |
TextAlign: Right |
| TextBox |
 |
txtItem3Quantity |
0 |
TextAlign: Right |
| TextBox |
 |
txtItem3SubTotal |
0.00 |
TextAlign: Right |
| ComboBox |
 |
cbxItem4Name |
None |
Items:
None
Women Suit
Dress
Regular Skirt
Skirt With Hook
Men's Suit 2Pc
Men's Suit 3Pc
Sweaters
Silk Shirt
Tie
Coat
Jacket
Swede |
| TextBox |
 |
txtItem4UnitPrice |
0.00 |
TextAlign: Right |
| TextBox |
 |
txtItem4Quantity |
0 |
TextAlign: Right |
| TextBox |
 |
txtItem4SubTotal |
0.00 |
TextAlign: Right |
| GroupBox |
 |
|
Order Summary |
|
| Label |
 |
|
Cleaning Total: |
|
| TextBox |
 |
txtCleaningTotal |
0.00 |
TextAlign: Right |
| Label |
 |
|
Tax Rate: |
|
| TextBox |
 |
txtTaxRate |
7.75 |
TextAlign: Right |
| Label |
 |
|
% |
|
| Label |
 |
|
Tax Amount: |
|
| TextBox |
 |
txtTaxAmount |
0.00 |
TextAlign: Right |
| Label |
 |
|
Net Total: |
|
| TextBox |
 |
txtNetPrice |
0.00 |
TextAlign: Right |
| Button |
 |
btnPrint |
Print... |
|
| Button |
 |
btnPrintPreview |
Print Preview... |
|
| Button |
 |
btnClose |
Close |
|
|
- Double-click the Time Left control and implement its ValueChanged event as
follows:
private void dtpTimeLeft_ValueChanged(object sender, EventArgs e)
{
DateTime dateLeft = this.dtpDateLeft.Value;
DateTime timeLeft = this.dtpTimeLeft.Value;
DateTime time9AM = new DateTime(timeLeft.Year, timeLeft.Month,
timeLeft.Day, 9, 0, 0);
// If the customer leaves clothes before 9AM...
if (timeLeft <= time9AM)
{
// ... then they should be ready the same day after 5PM
this.dtpDateExpected.Value = dateLeft;
this.dtpTimeExpected.Value = new DateTime(dateLeft.Year,
dateLeft.Month,
dateLeft.Day, 17, 0, 0);
}
else
{
// If the clothes were left after 9AM,
// then they will be available
// the following business morning at 8AM
// If the following day is Sunday,
// then they will be ready the following Monday
if (dateLeft.DayOfWeek == DayOfWeek.Saturday)
{
dtpDateExpected.Value = dateLeft.AddDays(2.00D);
dtpTimeExpected.Value = new DateTime(dateLeft.Year,
dateLeft.Month,
dateLeft.Day + 2, 8, 0, 0);
}
else
{
dtpDateExpected.Value = new DateTime(dateLeft.Year,
dateLeft.Month,
dateLeft.Day + 1);
dtpTimeExpected.Value = new DateTime(dateLeft.Year,
dateLeft.Month,
dateLeft.Day + 1, 8, 0, 0);
}
}
}
|
- Return to the form
- From the Printing section of the Toolbox, click PrintDocument and click
the form
- While the new control is still selected, in the Properties window, click
the Properties button, click (Name), type docPrint and press Enter
- Under the form, double-click docPrint and implement its event as follows:
private void docPrint_PrintPage(object sender,
System.Drawing.Printing.PrintPageEventArgs e)
{
e.Graphics.DrawLine(new Pen(Color.Black, 2), 60, 90, 720, 90);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 60, 93, 720, 93);
string strDisplay = "Georgetown Cleaning Services";
System.Drawing.Font fntString = new Font("Times New Roman", 28,
FontStyle.Bold);
e.Graphics.DrawString(strDisplay, fntString,
Brushes.Black, 120, 100);
strDisplay = "Customer Cleaning Order";
fntString = new System.Drawing.Font("Times New Roman", 18,
FontStyle.Bold);
e.Graphics.DrawString(strDisplay, fntString,
Brushes.Black, 220, 150);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 60, 184, 720, 184);
e.Graphics.DrawLine(new Pen(Color.Black, 2), 60, 188, 720, 188);
fntString = new System.Drawing.Font("Times New Roman", 12,
FontStyle.Bold);
e.Graphics.DrawString("", fntString,
Brushes.Black, 80, 200);
fntString = new System.Drawing.Font("Times New Roman", 12,
FontStyle.Bold);
e.Graphics.DrawString("Customer Identification: ", fntString,
Brushes.Black, 100, 220);
fntString = new System.Drawing.Font("Times New Roman", 12,
FontStyle.Regular);
e.Graphics.DrawString(txtCustomerName.Text + " - " +
txtCustomerPhone.Text, fntString,
Brushes.Black, 300, 220); ;
e.Graphics.DrawLine(new Pen(Color.Black, 1), 100, 240, 700, 240);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString("Date Left: ", fntString,
Brushes.Black, 100, 260);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(dtpDateLeft.Value.ToString("D"), fntString,
Brushes.Black, 300, 260);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 100, 280, 700, 280);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString("Time Left: ", fntString,
Brushes.Black, 500, 260);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(dtpTimeLeft.Value.ToString("t"), fntString,
Brushes.Black, 620, 260);
fntString = new System.Drawing.Font("Times New Roman",
12, FontStyle.Bold);
e.Graphics.DrawString("Date Expected: ", fntString,
Brushes.Black, 100, 300);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(dtpDateExpected.Value.ToString("D"),
fntString, Brushes.Black, 300, 300);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString("Time Expected: ", fntString,
Brushes.Black, 500, 300);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(dtpTimeExpected.Value.ToString("t"),
fntString, Brushes.Black, 620, 300);
e.Graphics.DrawLine(new Pen(Color.Black, 2), 100, 320, 700, 320);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString("Item Type",
fntString, Brushes.Black, 140, 350);
e.Graphics.DrawString("Unit Price",
fntString, Brushes.Black, 300, 350);
e.Graphics.DrawString("Quantity",
fntString, Brushes.Black, 405, 350);
e.Graphics.DrawString("Sub-Total",
fntString, Brushes.Black, 500, 350);
e.Graphics.DrawLine(new Pen(Color.Black, 2), 140, 370, 640, 370);
StringFormat fmtString = new StringFormat();
fmtString.Alignment = StringAlignment.Far;
e.Graphics.DrawString("Shirts",
fntString, Brushes.Black, 150, 380);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(txtUnitPriceShirts.Text, fntString,
Brushes.Black, 350, 380, fmtString);
e.Graphics.DrawString(txtQuantityShirts.Text, fntString,
Brushes.Black, 440, 380, fmtString);
e.Graphics.DrawString(txtSubTotalShirts.Text, fntString,
Brushes.Black, 550, 380, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 140, 400, 640, 400);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString("Pants",
fntString, Brushes.Black, 150, 410);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(txtUnitPricePants.Text, fntString,
Brushes.Black, 350, 410, fmtString);
e.Graphics.DrawString(txtQuantityPants.Text, fntString,
Brushes.Black, 440, 410, fmtString);
e.Graphics.DrawString(txtSubTotalPants.Text, fntString,
Brushes.Black, 550, 410, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 140, 430, 640, 430);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString(cbxItem1.Text,
fntString, Brushes.Black, 150, 440);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(txtUnitPriceItem1.Text, fntString,
Brushes.Black, 350, 440, fmtString);
e.Graphics.DrawString(txtQuantityItem1.Text, fntString,
Brushes.Black, 440, 440, fmtString);
e.Graphics.DrawString(txtSubTotalItem1.Text, fntString,
Brushes.Black, 550, 440, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 140, 460, 640, 460);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString(cbxItem2.Text,
fntString, Brushes.Black, 150, 470);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(txtUnitPriceItem2.Text, fntString,
Brushes.Black, 350, 470, fmtString);
e.Graphics.DrawString(txtQuantityItem2.Text, fntString,
Brushes.Black, 440, 470, fmtString);
e.Graphics.DrawString(txtSubTotalItem2.Text, fntString,
Brushes.Black, 550, 470, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 140, 490, 640, 490);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString(cbxItem3.Text,
fntString, Brushes.Black, 150, 500);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(txtUnitPriceItem3.Text, fntString,
Brushes.Black, 350, 500, fmtString);
e.Graphics.DrawString(txtQuantityItem3.Text, fntString,
Brushes.Black, 440, 500, fmtString);
e.Graphics.DrawString(txtSubTotalItem3.Text, fntString,
Brushes.Black, 550, 500, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1), 140, 520, 640, 520);
fntString = new Font("Times New Roman", 12, FontStyle.Bold);
e.Graphics.DrawString(cbxItem4.Text,
fntString, Brushes.Black, 150, 530);
fntString = new Font("Times New Roman", 12, FontStyle.Regular);
e.Graphics.DrawString(txtUnitPriceItem4.Text, fntString,
Brushes.Black, 350, 530, fmtString);
e.Graphics.DrawString(txtQuantityItem4.Text, fntString,
Brushes.Black, 440, 530, fmtString);
e.Graphics.DrawString(txtSubTotalItem4.Text, fntString,
Brushes.Black, 550, 530, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 2), 140, 550, 640, 550);
fntString = new System.Drawing.Font("Times New Roman", 12,
FontStyle.Bold);
e.Graphics.DrawString("Order Summary", fntString,
Brushes.Black, 260, 600);
e.Graphics.DrawLine(new Pen(Color.Black, 2), 220, 620, 560, 620);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Bold);
e.Graphics.DrawString("Cleaning Total:", fntString,
Brushes.Black, 260, 630);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Regular);
e.Graphics.DrawString(txtCleaningTotal.Text, fntString,
Brushes.Black, 440, 630, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1),
220, 650, 520, 650);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Bold);
e.Graphics.DrawString("Tax Rate:", fntString,
Brushes.Black, 260, 660);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Regular);
e.Graphics.DrawString(txtTaxRate.Text, fntString,
Brushes.Black, 440, 660, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1),
220, 680, 520, 680);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Bold);
e.Graphics.DrawString("Tax Amount:", fntString,
Brushes.Black, 260, 690);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Regular);
e.Graphics.DrawString(txtTaxAmount.Text, fntString,
Brushes.Black, 440, 690, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 1),
220, 710, 520, 710);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Bold);
e.Graphics.DrawString("Net Price:", fntString,
Brushes.Black, 260, 720);
fntString = new System.Drawing.Font("Times New Roman",
10, FontStyle.Regular);
e.Graphics.DrawString(txtNetPrice.Text, fntString,
Brushes.Black, 440, 720, fmtString);
e.Graphics.DrawLine(new Pen(Color.Black, 2),
200, 740, 560, 740);
}
|
- Return to the form
- From the Printing section of the Toolbox, click PrintDialog and click the
form
- In the Properties window, change its Name to dlgPrint
- Still in the Properties windows, set its Document property to docPrint
- On the main menu of the form, click File and double-click Print
- Implement the event as follows:
private void mnuFilePrint_Click(object sender, EventArgs e)
{
if (dlgPrint.ShowDialog() == DialogResult.OK)
docPrint.Print();
}
|
- Return to the form
- From the Printing section of the Toolbox, click PrintPreviewDialog and
click the form
- In the Properties window, change its Name to dlgPrintPreview
- Still in the Properties windows, set its Document property to docPrint
- On the main menu of the form, click File and double-click Print Preview
- Implement the event as follows:
private void mnuFilePrintPreview_Click(object sender, EventArgs e)
{
dlgPrintPreview.ShowDialog();
}
|
- Save the file
|
Locating an Element Using its Index |
|
Consider the following XML file named videos.xml:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
<video>
<title>The Day After Tomorrow</title>
<director>Roland Emmerich</director>
<length>124 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
<video>
<title>Other People's Money</title>
<director>Alan Brunstein</director>
<length>114 Minutes</length>
<format>VHS</format>
<rating>PG-13</rating>
</video>
</videos>
In Lesson 8, we saw that the
XmlNodeList class was equipped with both a method named Item and an indexed property (named
Item). Their syntaxes are:
public abstract XmlNode Item(int index);
public virtual XmlNode this[int i] { get; }
These two members allow you to access an element based on
its index. Here are examples:
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;
using System.IO;
using System.Xml;
namespace VideoCollection1
{
public partial class Exercise : Form
{
public Exercise()
{
InitializeComponent();
}
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
XmlElement elmRoot = xmlDoc.DocumentElement;
XmlNodeList lstVideos = elmRoot.ChildNodes;
MessageBox.Show(lstVideos[1].InnerText);
MessageBox.Show(lstVideos.Item(3).InnerXml);
}
}
}
}
This would produce:


You can use this characteristic to locate a node.
Because XML is very flexible with the names (you can have two child nodes that
have the same name) and values (you can have two child nodes that have the same
value) of nodes, when creating an XML file, it is your responsibility to create
a scheme that would eventually allow you to uniquely identify each element.
|
Practical
Learning: Locating an Element Using its Index
|
|
- On the form, double-click the New Cleaning Order button and implement its
event as follows:
private void btnNewCleaningOrder_Click(object sender, EventArgs e)
{
int ReceiptNumber = 1000;
XmlDocument docCleaningOrders = new XmlDocument();
Directory.CreateDirectory(@"C:\Georgetown Cleaning Services");
string Filename =
@"C:\Georgetown Cleaning Services\cleaningorders.xml";
// If some payments were previously made
if (File.Exists(Filename))
{
// Open the payments.xml file
docCleaningOrders.Load(Filename);
// Locate the root element
XmlElement elmCleaningOrder =
docCleaningOrders.DocumentElement;
// Get a list of the child nodes
XmlNodeList lstCleaningOrders =
elmCleaningOrder.ChildNodes;
// Get the last student number
ReceiptNumber =
int.Parse(lstCleaningOrders[lstCleaningOrders.Count
- 1].FirstChild.InnerText);
}
txtReceiptNumber.Text = (ReceiptNumber + 1).ToString();
txtCustomerName.Text = "";
txtCustomerPhone.Text = "";
dtpDateLeft.Value = DateTime.Today;
dtpTimeLeft.Value = DateTime.Today;
dtpDateExpected.Value = DateTime.Today;
dtpTimeExpected.Value = DateTime.Today;
cbxOrderStatus.Text = "Not Yet Ready";
dtpDatePickedUp.Value = DateTime.Today;
dtpTimePickedUp.Value = DateTime.Today;
txtShirtsUnitPrice.Text = "1.25";
txtShirtsQuantity.Text = "0";
txtShirtsSubTotal.Text = "0.00";
txtPantsUnitPrice.Text = "1.95";
txtPantsQuantity.Text = "0";
txtPantsSubTotal.Text = "0.00";
cbxItem1Name.Text = "None";
txtItem1UnitPrice.Text = "0.00";
txtItem1Quantity.Text = "0";
txtItem1SubTotal.Text = "0.00";
cbxItem2Name.Text = "None";
txtItem2UnitPrice.Text = "0.00";
txtItem2Quantity.Text = "0";
txtItem2SubTotal.Text = "0.00";
cbxItem3Name.Text = "None";
txtItem3UnitPrice.Text = "0.00";
txtItem3Quantity.Text = "0";
txtItem3SubTotal.Text = "0.00";
cbxItem4Name.Text = "None";
txtItem4UnitPrice.Text = "0.00";
txtItem4Quantity.Text = "0";
txtItem4SubTotal.Text = "0.00";
txtCleaningTotal.Text = "0.00";
txtTaxRate.Text = "7.75";
txtTaxAmount.Text = "0.00";
txtCleaningTotal.Text = "0.00";
txtCustomerName.Focus();
}
|
- Return to the form and double-click an unoccupied area of its body
- Implement its event as follows:
private void Central_Load(object sender, EventArgs e)
{
btnNewCleaningOrder_Click(sender, e);
}
|
- Save the file
|
Locating an Element Using its Name |
|
To assist you with locating the first child node of a node, the
XmlNode class is equipped with an indexed property (named Item)
overloaded with two versions. One of the versions is declared as follows:
public virtual XmlElement this[string name] { get; }
This indexed property takes the name of a node as argument.
After the property has been called, the parser checks the child nodes of the
element on which the property was applied. If the parser finds a node with that
name, it returns it as an XmlElement object. Here is an example:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
XmlElement elmRoot = xmlDoc.DocumentElement;
XmlNodeList lstVideos = elmRoot.ChildNodes;
MessageBox.Show(lstVideos[1]["director"].InnerText);
MessageBox.Show(lstVideos.Item(3)["format"].InnerXml);
}
}
Based on the videos.xml file we had earlier, this would produce:
If the node has more than one child with the same name, then
it would return the first child with that name. You can use this characteristic
to look for, or locate, an element.
|
Practical
Learning: Locating an Element Using its Name
|
|
- On the form, double-click the Open button and implement the event as follows:
private void btnOpen_Click(object sender, EventArgs e)
{
string Filename =
@"C:\Georgetown Cleaning Services\cleaningorders.xml";
XmlDocument docCleaningOrders = new XmlDocument();
if( File.Exists(Filename) )
{
bool found = false;
docCleaningOrders.Load(Filename);
XmlElement elmCleaningOrder =
docCleaningOrders.DocumentElement;
XmlNodeList lstCleaningOrders =
elmCleaningOrder.ChildNodes;
for (int i = 0; i < lstCleaningOrders.Count; i++)
{
if (lstCleaningOrders[i].FirstChild.InnerText ==
txtReceiptNumber.Text)
{
found = true;
txtCustomerName.Text =
lstCleaningOrders[i]["CustomerName"].InnerText;
txtCustomerPhone.Text =
lstCleaningOrders[i]["CustomerPhone"].InnerText;
dtpDateLeft.Value =
DateTime.Parse(lstCleaningOrders[i]["DateLeft"].InnerText);
dtpTimeLeft.Value =
DateTime.Parse(lstCleaningOrders[i]["TimeLeft"].InnerText);
dtpDateExpected.Value =
DateTime.Parse(lstCleaningOrders[i]["DateExpected"].InnerText);
dtpTimeExpected.Value =
DateTime.Parse(lstCleaningOrders[i]["TimeExpected"].InnerText);
cbxOrderStatus.Text =
lstCleaningOrders[i]["OrderStatus"].InnerText;
dtpDatePickedUp.Value =
DateTime.Parse(lstCleaningOrders[i]["DatePickedUp"].InnerText);
dtpTimePickedUp.Value =
DateTime.Parse(lstCleaningOrders[i]["TimePickedUp"].InnerText);
txtShirtsUnitPrice.Text =
lstCleaningOrders[i]["ShirtsUnitPrice"].InnerText;
txtShirtsQuantity.Text =
lstCleaningOrders[i]["ShirtsQuantity"].InnerText;
txtShirtsSubTotal.Text =
lstCleaningOrders[i]["ShirtsSubTotal"].InnerText;
txtPantsUnitPrice.Text =
lstCleaningOrders[i]["PantsUnitPrice"].InnerText;
txtPantsQuantity.Text =
lstCleaningOrders[i]["PantsQuantity"].InnerText;
txtPantsSubTotal.Text =
lstCleaningOrders[i]["PantsSubTotal"].InnerText;
cbxItem1Name.Text = lstCleaningOrders[i]["Item1Name"].InnerText;
txtItem1UnitPrice.Text =
lstCleaningOrders[i]["Item1UnitPrice"].InnerText;
txtItem1Quantity.Text =
lstCleaningOrders[i]["Item1Quantity"].InnerText;
txtItem1SubTotal.Text =
lstCleaningOrders[i]["Item1SubTotal"].InnerText;
cbxItem2Name.Text = lstCleaningOrders[i]["Item2Name"].InnerText;
txtItem2UnitPrice.Text =
lstCleaningOrders[i]["Item2UnitPrice"].InnerText;
txtItem2Quantity.Text =
lstCleaningOrders[i]["Item2Quantity"].InnerText;
txtItem2SubTotal.Text =
lstCleaningOrders[i]["Item2SubTotal"].InnerText;
cbxItem3Name.Text = lstCleaningOrders[i]["Item3Name"].InnerText;
txtItem3UnitPrice.Text =
lstCleaningOrders[i]["Item3UnitPrice"].InnerText;
txtItem3Quantity.Text =
lstCleaningOrders[i]["Item3Quantity"].InnerText;
txtItem3SubTotal.Text =
lstCleaningOrders[i]["Item3SubTotal"].InnerText;
cbxItem4Name.Text = lstCleaningOrders[i]["Item4Name"].InnerText;
txtItem4UnitPrice.Text =
lstCleaningOrders[i]["Item4UnitPrice"].InnerText;
txtItem4Quantity.Text =
lstCleaningOrders[i]["Item4Quantity"].InnerText;
txtItem4SubTotal.Text =
lstCleaningOrders[i]["Item4SubTotal"].InnerText;
txtCleaningTotal.Text =
lstCleaningOrders[i]["CleaningTotal"].InnerText;
txtTaxRate.Text = lstCleaningOrders[i]["TaxRate"].InnerText;
txtTaxAmount.Text = lstCleaningOrders[i]["TaxAmount"].InnerText;
txtNetPrice.Text = lstCleaningOrders[i]["NetPrice"].InnerText;
break;
}
}
if (found == false)
MessageBox.Show("There is no cleaning order with that receipt number");
}
else
MessageBox.Show("There is no file that holds the list of cleaning orders");
}
private void SaveCleaningOrder()
{
// This variable will be used to know
// if the receipt number already exists in the file
bool ReceiptFound = false;
// This variable will be used to know whether we are creating
// a new cleaning order or if we are only updating
// an existing cleaning order
XmlNode ExistingCleaningOrder = null;
int ReceiptNumber = int.Parse(txtReceiptNumber.Text);
// We will need a reference to the DOM
XmlDocument docCleaningOrders = new XmlDocument();
// Here is the XML file that holds the cleaning orders
string Filename =
@"C:\Georgetown Cleaning Services\cleaningorders.xml";
// If there is no receipt number, don't do anything
if (txtReceiptNumber.Text.Length == 0)
{
MessageBox.Show("The cleaning order cannot be created " +
"because the receipt number is missing");
return;
}
// If the file exists,...
if (File.Exists(Filename))
{
// then open it
docCleaningOrders.Load(Filename);
XmlElement elmCleaningOrder = docCleaningOrders.DocumentElement;
XmlNodeList lstCleaningOrders = elmCleaningOrder.ChildNodes;
for (int i = 0; i < lstCleaningOrders.Count; i++)
{
XmlNode node = lstCleaningOrders.Item(i);
if (lstCleaningOrders.Item(i).FirstChild.InnerText ==
txtReceiptNumber.Text)
{
ReceiptFound = true;
ExistingCleaningOrder = lstCleaningOrders[i];
ReceiptNumber =
int.Parse(ExistingCleaningOrder["ReceiptNumber"].InnerText);
break;
}
}
if (ReceiptFound == true)
{
ExistingCleaningOrder["CustomerName"].InnerText =
txtCustomerName.Text;
ExistingCleaningOrder["CustomerPhone"].InnerText =
txtCustomerPhone.Text;
ExistingCleaningOrder["DateLeft"].InnerText =
dtpDateLeft.Value.ToString("d");
ExistingCleaningOrder["TimeLeft"].InnerText =
dtpTimeLeft.Value.ToString("t");
ExistingCleaningOrder["DateExpected"].InnerText =
dtpDateExpected.Value.ToString("d");
ExistingCleaningOrder["TimeExpected"].InnerText =
dtpTimeExpected.Value.ToString("t");
ExistingCleaningOrder["OrderStatus"].InnerText =
cbxOrderStatus.Text;
ExistingCleaningOrder["DatePickedUp"].InnerText =
dtpDatePickedUp.Value.ToString("d");
ExistingCleaningOrder["TimePickedUp"].InnerText =
dtpTimePickedUp.Value.ToString("t");
ExistingCleaningOrder["ShirtsUnitPrice"].InnerText =
txtShirtsUnitPrice.Text;
ExistingCleaningOrder["ShirtsQuantity"].InnerText =
txtShirtsQuantity.Text;
ExistingCleaningOrder["ShirtsSubTotal"].InnerText =
txtShirtsSubTotal.Text;
ExistingCleaningOrder["PantsUnitPrice"].InnerText =
txtPantsUnitPrice.Text;
ExistingCleaningOrder["PantsQuantity"].InnerText =
txtPantsQuantity.Text;
ExistingCleaningOrder["PantsSubTotal"].InnerText =
txtPantsSubTotal.Text;
ExistingCleaningOrder["Item1Name"].InnerText =
cbxItem1Name.Text;
ExistingCleaningOrder["Item1UnitPrice"].InnerText =
txtItem1UnitPrice.Text;
ExistingCleaningOrder["Item1Quantity"].InnerText =
txtItem1Quantity.Text;
ExistingCleaningOrder["Item1SubTotal"].InnerText =
txtItem1SubTotal.Text;
ExistingCleaningOrder["Item2Name"].InnerText =
cbxItem2Name.Text;
ExistingCleaningOrder["Item2UnitPrice"].InnerText =
txtItem2UnitPrice.Text;
ExistingCleaningOrder["Item2Quantity"].InnerText =
txtItem2Quantity.Text;
ExistingCleaningOrder["Item2SubTotal"].InnerText =
txtItem2SubTotal.Text;
ExistingCleaningOrder["Item3Name"].InnerText =
cbxItem3Name.Text;
ExistingCleaningOrder["Item3UnitPrice"].InnerText =
txtItem3UnitPrice.Text;
ExistingCleaningOrder["Item3Quantity"].InnerText =
txtItem3Quantity.Text;
ExistingCleaningOrder["Item3SubTotal"].InnerText =
txtItem3SubTotal.Text;
ExistingCleaningOrder["Item4Name"].InnerText =
cbxItem4Name.Text;
ExistingCleaningOrder["Item4UnitPrice"].InnerText =
txtItem4UnitPrice.Text;
ExistingCleaningOrder["Item4Quantity"].InnerText =
txtItem4Quantity.Text;
ExistingCleaningOrder["Item4SubTotal"].InnerText =
txtItem4SubTotal.Text;
ExistingCleaningOrder["CleaningTotal"].InnerText =
txtCleaningTotal.Text;
ExistingCleaningOrder["TaxRate"].InnerText =
txtTaxRate.Text;
ExistingCleaningOrder["TaxAmount"].InnerText =
txtTaxAmount.Text;
ExistingCleaningOrder["NetPrice"].InnerText =
txtNetPrice.Text;
}
else // The receipt number was not found. So, create a new cleaning order
{
XmlElement nodRoot = docCleaningOrders.DocumentElement;
XmlElement elmXML =
docCleaningOrders.CreateElement("CleaningOrder");
string strNewCleaningOrder =
"<ReceiptNumber>" + txtReceiptNumber.Text +
"</ReceiptNumber>" + "<CustomerName>" +
txtCustomerName.Text + "</CustomerName>" +
"<CustomerPhone>" + txtCustomerPhone.Text +
"</CustomerPhone>" + "<DateLeft>" +
dtpDateLeft.Value.ToString("d") + "</DateLeft>" +
"<TimeLeft>" + dtpTimeLeft.Value.ToString("t") +
"</TimeLeft>" + "<DateExpected>" +
dtpDateExpected.Value.ToString("d") +
"</DateExpected>" + "<TimeExpected>" +
dtpTimeExpected.Value.ToString("t") +
"</TimeExpected>" + "<OrderStatus>" +
cbxOrderStatus.Text + "</OrderStatus>" +
"<DatePickedUp>" + dtpDatePickedUp.Value.ToString("d") +
"</DatePickedUp>" + "<TimePickedUp>" +
dtpTimePickedUp.Value.ToString("t") +
"</TimePickedUp>" + "<ShirtsUnitPrice>" +
txtShirtsUnitPrice.Text + "</ShirtsUnitPrice>" +
"<ShirtsQuantity>" + txtShirtsQuantity.Text +
"</ShirtsQuantity>" + "<ShirtsSubTotal>" +
txtShirtsSubTotal.Text + "</ShirtsSubTotal>" +
"<PantsUnitPrice>" + txtPantsUnitPrice.Text +
"</PantsUnitPrice>" + "<PantsQuantity>" +
txtPantsQuantity.Text + "</PantsQuantity>" +
"<PantsSubTotal>" + txtPantsSubTotal.Text +
"</PantsSubTotal>" + "<Item1Name>" +
cbxItem1Name.Text + "</Item1Name>" +
"<Item1UnitPrice>" + txtItem1UnitPrice.Text +
"</Item1UnitPrice>" + "<Item1Quantity>" +
txtItem1Quantity.Text + "</Item1Quantity>" +
"<Item1SubTotal>" + txtItem1SubTotal.Text +
"</Item1SubTotal>" + "<Item2Name>" +
cbxItem2Name.Text + "</Item2Name>" +
"<Item2UnitPrice>" + txtItem2UnitPrice.Text +
"</Item2UnitPrice>" + "<Item2Quantity>" +
txtItem2Quantity.Text + "</Item2Quantity>" +
"<Item2SubTotal>" + txtItem2SubTotal.Text +
"</Item2SubTotal>" + "<Item3Name>" +
cbxItem3Name.Text + "</Item3Name>" +
"<Item3UnitPrice>" + txtItem3UnitPrice.Text +
"</Item3UnitPrice>" + "<Item3Quantity>" +
txtItem3Quantity.Text + "</Item3Quantity>" +
"<Item3SubTotal>" + txtItem3SubTotal.Text +
"</Item3SubTotal>" + "<Item4Name>" +
cbxItem4Name.Text + "</Item4Name>" +
"<Item4UnitPrice>" + txtItem4UnitPrice.Text +
"</Item4UnitPrice>" + "<Item4Quantity>" +
txtItem4Quantity.Text + "</Item4Quantity>" +
"<Item4SubTotal>" + txtItem4SubTotal.Text +
"</Item4SubTotal>" + "<CleaningTotal>" +
txtCleaningTotal.Text + "</CleaningTotal>" +
"<TaxRate>" + txtTaxRate.Text + "</TaxRate>" +
"<TaxAmount>" + txtTaxAmount.Text + "</TaxAmount>" +
"<NetPrice>" + txtNetPrice.Text + "</NetPrice>";
elmXML.InnerXml = strNewCleaningOrder;
docCleaningOrders.DocumentElement.AppendChild(elmXML);
}
// docCleaningOrders.Save(Filename);
}
// If there is no such a file, prepare to create it
else //if (!File.Exists(Filename))
{
docCleaningOrders.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<CleaningOrders></CleaningOrders>");
XmlElement nodRoot = docCleaningOrders.DocumentElement;
XmlElement elmXML = docCleaningOrders.CreateElement("CleaningOrder");
string strNewCleaningOrder =
"<ReceiptNumber>" + txtReceiptNumber.Text +
"</ReceiptNumber>" + "<CustomerName>" +
txtCustomerName.Text + "</CustomerName>" +
"<CustomerPhone>" + txtCustomerPhone.Text +
"</CustomerPhone>" + "<DateLeft>" +
dtpDateLeft.Value.ToString("d") + "</DateLeft>" +
"<TimeLeft>" + dtpTimeLeft.Value.ToString("t") +
"</TimeLeft>" + "<DateExpected>" +
dtpDateExpected.Value.ToString("d") +
"</DateExpected>" + "<TimeExpected>" +
dtpTimeExpected.Value.ToString("t") +
"</TimeExpected>" + "<OrderStatus>" +
cbxOrderStatus.Text + "</OrderStatus>" +
"<DatePickedUp>" + dtpDatePickedUp.Value.ToString("d") +
"</DatePickedUp>" + "<TimePickedUp>" +
dtpTimePickedUp.Value.ToString("t") +
"</TimePickedUp>" + "<ShirtsUnitPrice>" +
txtShirtsUnitPrice.Text + "</ShirtsUnitPrice>" +
"<ShirtsQuantity>" + txtShirtsQuantity.Text +
"</ShirtsQuantity>" + "<ShirtsSubTotal>" +
txtShirtsSubTotal.Text + "</ShirtsSubTotal>" +
"<PantsUnitPrice>" + txtPantsUnitPrice.Text +
"</PantsUnitPrice>" + "<PantsQuantity>" +
txtPantsQuantity.Text + "</PantsQuantity>" +
"<PantsSubTotal>" + txtPantsSubTotal.Text +
"</PantsSubTotal>" + "<Item1Name>" +
cbxItem1Name.Text + "</Item1Name>" +
"<Item1UnitPrice>" + txtItem1UnitPrice.Text +
"</Item1UnitPrice>" + "<Item1Quantity>" +
txtItem1Quantity.Text + "</Item1Quantity>" +
"<Item1SubTotal>" + txtItem1SubTotal.Text +
"</Item1SubTotal>" + "<Item2Name>" +
cbxItem2Name.Text + "</Item2Name>" +
"<Item2UnitPrice>" + txtItem2UnitPrice.Text +
"</Item2UnitPrice>" + "<Item2Quantity>" +
txtItem2Quantity.Text + "</Item2Quantity>" +
"<Item2SubTotal>" + txtItem2SubTotal.Text +
"</Item2SubTotal>" + "<Item3Name>" +
cbxItem3Name.Text + "</Item3Name>" +
"<Item3UnitPrice>" + txtItem3UnitPrice.Text +
"</Item3UnitPrice>" + "<Item3Quantity>" +
txtItem3Quantity.Text + "</Item3Quantity>" +
"<Item3SubTotal>" + txtItem3SubTotal.Text +
"</Item3SubTotal>" + "<Item4Name>" +
cbxItem4Name.Text + "</Item4Name>" +
"<Item4UnitPrice>" + txtItem4UnitPrice.Text +
"</Item4UnitPrice>" + "<Item4Quantity>" +
txtItem4Quantity.Text + "</Item4Quantity>" +
"<Item4SubTotal>" + txtItem4SubTotal.Text +
"</Item4SubTotal>" + "<CleaningTotal>" +
txtCleaningTotal.Text + "</CleaningTotal>" +
"<TaxRate>" + txtTaxRate.Text + "</TaxRate>" +
"<TaxAmount>" + txtTaxAmount.Text + "</TaxAmount>" +
"<NetPrice>" + txtNetPrice.Text + "</NetPrice>";
elmXML.InnerXml = strNewCleaningOrder;
docCleaningOrders.DocumentElement.AppendChild(elmXML);
}
docCleaningOrders.Save(Filename);
}
|
- Return to the form and click the unit price text box that corresponds to the pants
- Press and hold Shift
- Click the unit price text boxes for item 1, item 2, item 3, and item 4
- Click each text box under the Qty label
- Click the Tax Rate text box
- Release Shift
- In the Events section of the Properties window, double-click Leave and
implement the event as follows:
private void txtShirtsUnitPrice_Leave(object sender, EventArgs e)
{
double unitPriceShirts = 0.00, unitPricePants = 0.00,
unitPriceItem1 = 0.00, unitPriceItem2 = 0.00,
unitPriceItem3 = 0.00, unitPriceItem4 = 0.00;
double subTotalShirts = 0.00, subTotalPants = 0.00,
subTotalItem1 = 0.00, subTotalItem2 = 0.00,
subTotalItem3 = 0.00, subTotalItem4 = 0.00;
int qtyShirts = 1, qtyPants = 1, qtyItem1 = 1,
qtyItem2 = 1, qtyItem3 = 1, qtyItem4 = 4;
double cleaningTotal = 0.00, taxRate = 0.00,
taxAmount = 0.00, netPrice = 0.00;
// Retrieve the unit price of this item
// Just in case the user types an invalid value,
// we are using a try...catch
try
{
unitPriceShirts = double.Parse(txtShirtsUnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the price of " +
"shirts is not valid" +
"\nPlease try again");
return;
}
// Retrieve the number of this item
// Just in case the user types an invalid value,
// we are using a try...catch
try
{
qtyShirts = int.Parse(txtShirtsQuantity.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the number of " +
"shirts is not valid" +
"\nPlease try again");
return;
}
try
{
unitPricePants = double.Parse(txtPantsUnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the price of " +
"pants is not valid" +
"\nPlease try again");
return;
}
try
{
qtyPants = int.Parse(txtPantsQuantity.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the number of " +
"pants is not valid" +
"\nPlease try again");
return;
}
if ((cbxItem1Name.Text == "None") ||
(cbxItem1Name.Text == ""))
{
qtyItem1 = 0;
unitPriceItem1 = 0.00;
}
else
{
try
{
unitPriceItem1 = double.Parse(txtItem1UnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the price is not valid" +
"\nPlease try again");
return;
}
try
{
qtyItem1 = int.Parse(txtItem1Quantity.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered is not valid" +
"\nPlease try again");
return;
}
}
if ((cbxItem2Name.Text == "None") ||
(cbxItem2Name.Text == ""))
{
qtyItem2 = 0;
unitPriceItem2 = 0.00;
}
else
{
try
{
unitPriceItem2 = double.Parse(txtItem2UnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for " +
"the price is not valid" +
"\nPlease try again");
return;
}
try
{
qtyItem2 = int.Parse(txtItem2Quantity.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered is not valid" +
"\nPlease try again");
return;
}
}
if ((cbxItem3Name.Text == "None") ||
(cbxItem3Name.Text == ""))
{
qtyItem3 = 0;
unitPriceItem3 = 0.00;
}
else
{
try
{
unitPriceItem3 = double.Parse(txtItem3UnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the " +
"price is not valid" +
"\nPlease try again");
return;
}
try
{
qtyItem3 = int.Parse(txtItem3Quantity.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered is not valid" +
"\nPlease try again");
return;
}
}
if ((cbxItem4Name.Text == "None") || (cbxItem4Name.Text == ""))
{
qtyItem4 = 0;
unitPriceItem4 = 0.00;
}
else
{
try
{
unitPriceItem4 = double.Parse(txtItem4UnitPrice.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered for the price is not valid" +
"\nPlease try again");
return;
}
try
{
qtyItem4 = int.Parse(txtItem4Quantity.Text);
}
catch (FormatException)
{
MessageBox.Show("The value you entered is not valid" +
"\nPlease try again");
return;
}
}
// Calculate the sub-total for this item
subTotalShirts = qtyShirts * unitPriceShirts;
subTotalPants = qtyPants * unitPricePants;
subTotalItem1 = qtyItem1 * unitPriceItem1;
subTotalItem2 = qtyItem2 * unitPriceItem2;
subTotalItem3 = qtyItem3 * unitPriceItem3;
subTotalItem4 = qtyItem4 * unitPriceItem4;
// Calculate the total based on sub-totals
cleaningTotal = subTotalShirts + subTotalPants + subTotalItem1 +
subTotalItem2 + subTotalItem3 + subTotalItem4;
taxRate = double.Parse(txtTaxRate.Text);
// Calculate the amount owed for the taxes
taxAmount = cleaningTotal * taxRate / 100;
// Add the tax amount to the total order
netPrice = cleaningTotal + taxAmount;
// Display the sub-total in the corresponding text box
txtShirtsSubTotal.Text = subTotalShirts.ToString("F");
txtPantsSubTotal.Text = subTotalPants.ToString("F");
txtItem1SubTotal.Text = subTotalItem1.ToString("F");
txtItem2SubTotal.Text = subTotalItem2.ToString("F");
txtItem3SubTotal.Text = subTotalItem3.ToString("F");
txtItem4SubTotal.Text = subTotalItem4.ToString("F");
txtCleaningTotal.Text = cleaningTotal.ToString("F");
txtTaxAmount.Text = taxAmount.ToString("F");
txtNetPrice.Text = netPrice.ToString("F");
SaveCleaningOrder();
}
|
- Return to the form and double-click the Order Status combo box
- Implement the event as follows:
private void cbxOrderStatus_SelectedIndexChanged(object sender, EventArgs e)
{
SaveCleaningOrder();
}
|
- Return to the form and double-click the Date Picked Up control
- Implement the event as follows:
private void dtpDatePickedUp_ValueChanged(object sender, EventArgs e)
{
SaveCleaningOrder();
}
|
- Return to the form and double-click the Time Picked Up control
- Implement the event as follows:
private void dtpTimePickedUp_ValueChanged(object sender, EventArgs e)
{
SaveCleaningOrder();
}
|
- Return to the form and double-click the Close button
- Implement its event as follows:
private void btnClose_Click(object sender, EventArgs e)
{
Close();
}
|
- Execute the application
- Create a cleaning order
- Click New Cleaning Order and create a few more cleaning orders
- Close the form and return to your programming environment
|
Locating an Element Using a Tag Name |
|
To assist you with finding a node, the XmlDocument class is
equipped with the GetElementByTagName() method which is overloaded with
two versions. One of the syntaxes used is:
public virtual XmlNodeList GetElementsByTagName(string name);
This method takes as argument a string. The string must be
the name of a node. If at least one node that holds that name exists in the
file, this method returns a collection of the nodes with that name. If there is
no node with that name, the collection is returned empty and there is no
exception thrown.
Here is an example of calling the method:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of nodes whose name is Title
XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("title");
}
Once you have a list of the nodes of a particular criterion,
you can then act as you see fit. For example, For example, you can look for a
particular node that holds a text of your choice.
|
Adding an Element as a Last Child |
|
Once again, consider our Videos.xml file:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
<video>
<title>The Day After Tomorrow</title>
<director>Roland Emmerich</director>
<length>124 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
<video>
<title>Other People's Money</title>
<director>Alan Brunstein</director>
<length>114 Minutes</length>
<format>VHS</format>
<rating>PG-13</rating>
</video>
</videos>
Imagine you want to add a list of actors of the Her Alibi
video. The first action to take is to locate the video, which you can do by
calling the XmlDocument.GetElementsByTagName() method applied to a
collection of nodes whose names are video. From this list of nodes, you can look
for the node whose value is "Her Alibi". Once you have found this
element, get a reference to its parent. Then add the new node as a child its parent. This can be done as follows:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of nodes whose name is Title
XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("title");
// Now you can check each node of the list
foreach (XmlNode node in lstTitles)
{
if (node.InnerText == "Her Alibi")
{
// Create an element named Actors
XmlElement elmNew = xmlDoc.CreateElement("actors");
XmlNode elmParent = node.ParentNode;
// Add a new element named Actors to it
elmParent.AppendChild(elmNew);
xmlDoc.Save(Filename);
}
}
}
}
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
. . .
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
<actors />
</video>
. . .
</videos>
This code creates an empty element. If you want to create an
element that includes a value, create its text and add that text to the node. Here is an example:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of nodes whose name is Title
XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("title");
// Now you can check each node of the list
foreach (XmlNode node in lstTitles)
{
// When you get to a node, look for the element's value
// If you find an element whose value is Her Alibi
if (node.InnerText == "The Distinguished Gentleman")
{
// Create an element named Category
XmlElement elmNew = xmlDoc.CreateElement("category");
// Create the text of the new element
XmlText txtCatetory = xmlDoc.CreateTextNode("Comedy");
// Get a reference to the parent of the node we have found
XmlNode elmParent = node.ParentNode;
// Add the new element to the node we found
elmParent.AppendChild(elmNew);
// Specify the text of the new node
elmParent.LastChild.AppendChild(txtCatetory);
// Save the file
xmlDoc.Save(Filename);
}
}
}
}
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
<category>Comedy</category>
</video>
. . .
</videos>
Using the same approach combined with what we learned about
adding an item, you can add a new element that itself has child nodes. Here is
an example:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of nodes whose name is Title
XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("title");
// Now you can check each node of the list
foreach (XmlNode node in lstTitles)
{
// When you get to a node, look for the element's value
// If you find an element whose value is The Day After Tomorrow
if (node.InnerText == "The Day After Tomorrow")
{
// Create an element named Actors
XmlElement elmNew = xmlDoc.CreateElement("actors");
// Get a reference to the parent of the node we have found
XmlNode elmVideo = node.ParentNode;
// Add the new element to the node we found
elmVideo.AppendChild(elmNew);
// Create an element as a child of the new element
// Specify its name as Actor
elmNew = xmlDoc.CreateElement("actor");
// Create the text of the new element
XmlText txtActor = xmlDoc.CreateTextNode("Dennis Quaid");
// Add the new Actor element to the Actors node
elmVideo.LastChild.AppendChild(elmNew);
// Specify the text of the new node
elmVideo.LastChild.LastChild.AppendChild(txtActor);
// In the same way, add the other Actor nodes
elmNew = xmlDoc.CreateElement("actor");
txtActor = xmlDoc.CreateTextNode("Jake Gyllenhaal");
elmVideo.LastChild.AppendChild(elmNew);
elmVideo.LastChild.LastChild.AppendChild(txtActor);
elmNew = xmlDoc.CreateElement("actor");
txtActor = xmlDoc.CreateTextNode("Emmy Rossum");
elmVideo.LastChild.AppendChild(elmNew);
elmVideo.LastChild.LastChild.AppendChild(txtActor);
elmNew = xmlDoc.CreateElement("actor");
txtActor = xmlDoc.CreateTextNode("Dash Mihok");
elmVideo.LastChild.AppendChild(elmNew);
elmVideo.LastChild.LastChild.AppendChild(txtActor);
// Save the file
xmlDoc.Save(Filename);
}
}
}
}
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
. . .
<video>
<title>The Day After Tomorrow</title>
<director>Roland Emmerich</director>
<length>124 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
<actors>
<actor>Dennis Quaid</actor>
<actor>Jake Gyllenhaal</actor>
<actor>Emmy Rossum</actor>
<actor>Dash Mihok</actor>
</actors>
</video>
</videos>
You can also insert one or more elements as children of an
existing node after locating that node. Here is an example:
XML File
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
<category>Comedy</category>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Mins</length>
<format>DVD</format>
<rating>PG-13</rating>
<actors />
</video>
</videos>
Code Fragment:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of nodes whose name is Title
XmlNodeList lstTitles = xmlDoc.GetElementsByTagName("title");
// Now you can check each node of the list
foreach (XmlNode node in lstTitles)
{
// When you get to a node, look for the element's value
// If you find an element whose value is Her Alibi
if (node.InnerText == "Her Alibi")
{
// Get a reference to the video node that is
// the parent of the video titled Her Alibi
XmlNode elmVideo = node.ParentNode;
// Create a list of the child nodes of the Her alibi video
XmlNodeList lstActors = elmVideo.ChildNodes;
// Visit each item of the collection
// looking for an element named Actors
foreach (XmlNode nodActor in lstActors)
{
// If you find an element named Actors
if (nodActor.Name == "actors")
{
// Create a new element named Actor
// Specify its name as Actor
XmlElement elmNew = xmlDoc.CreateElement("actor");
// Create the text of the new element
XmlText txtActor = xmlDoc.CreateTextNode("Tom Selleck");
// Add the new Actor element to the Actors node
elmVideo.LastChild.AppendChild(elmNew);
// Specify the text of the new node
elmVideo.LastChild.LastChild.AppendChild(txtActor);
// Add other Actor nodes
elmNew = xmlDoc.CreateElement("actor");
txtActor = xmlDoc.CreateTextNode("Paulina Porizkova");
elmVideo.LastChild.AppendChild(elmNew);
elmVideo.LastChild.LastChild.AppendChild(txtActor);
elmNew = xmlDoc.CreateElement("actor");
txtActor = xmlDoc.CreateTextNode("William Daniels");
elmVideo.LastChild.AppendChild(elmNew);
elmVideo.LastChild.LastChild.AppendChild(txtActor);
// Save the file
xmlDoc.Save(Filename);
// Stop, in this example, we don't expect another Actors node
break;
}
}
}
}
}
}
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
<category>Comedy</category>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
<actors>
<actor>Tom Selleck</actor>
<actor>Paulina Porizkova</actor>
<actor>William Daniels</actor>
</actors>
</video>
</videos>
|
Inserting an Element Referencing a Sibling |
|
Instead of simply adding a new node at the end of child
nodes, you can specify any other position you want. For example, you may want
the new node to precede an existing child node. To support this operation, the XmlNode
class provides the InsertBefore() method. Its syntax is:
public virtual XmlNode InsertBefore(XmlNode newChild, XmlNode refChild);
The first argument of this method is the new node that will
be added. The second argument is the sibling that will succeed the new node.
Consider the following version of our Videos.xml file:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
<category>Comedy</category>
</video>
<video>
<title>Fatal Attraction</title>
<director>Adrian Lyne</director>
<length>119 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
</videos>
Imagine you want to create a new category element below the
director element whose name is Adrian Lyne. You can first get a list of videos.
Inside of each video, check the nodes and find out whether the video has a
director node whose text is Adrian Lyne. Once you find that node, you can add
the new element after it. Here is an example: private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of the videos
XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("video");
// visit each video
foreach (XmlNode node in lstVideos)
{
// Within a video, create a list of its children
XmlNodeList lstChildren = node.ChildNodes;
// Visit each child node
foreach (XmlNode dir in lstChildren)
{
// If the child node is (a director and its name is) Adrian Lyne
if (dir.InnerText == "Adrian Lyne")
{
// Create an element named Category
XmlElement elmNew = xmlDoc.CreateElement("category");
// Specify the text of the new element
elmNew.InnerText = "Drama";
// Insert the new node below the Adrian Lyne node Director
node.InsertAfter(elmNew, dir);
// Save the file
xmlDoc.Save(Filename);
// Stop
break;
}
}
}
}
}
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
<category>Comedy</category>
</video>
<video>
<title>Fatal Attraction</title>
<director>Adrian Lyne</director>
<category>Drama</category>
<length>119 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
</videos>
In the same way, you can insert a new node after a child of
a child (or of a child of a child of a child) of any node.
If you want to new node to be positioned after an existing child node, you can
call the XmlNode.InsertAfter() method. Its syntax is: public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild);
If you have a node you don't want or don't need anymore in
the file, you can delete it. To delete a node, the XmlNode class provides
the RemoveChild() method. Its syntax is:
public virtual XmlNode RemoveChild(XmlNode oldChild);
This method takes as argument the node to delete. If the
node exists, it would be deleted and the method would return the node that was
deleted. If the node does not exist, nothing would happen. To effectively use this method, you should
first locate the particular node you want to delete. You can look for it using
any of the logics we have applied so far. Once you find the node, you can then
delete it. Imagine you want to delete a node whose name is Director and whose
value is Bruce Beresford. Here is an example of calling this method to perform
the operation:
private void btnDocument_Click(object sender, EventArgs e)
{
string Filename = "videos.xml";
XmlDocument xmlDoc = new XmlDocument();
if (File.Exists(Filename))
{
xmlDoc.Load(Filename);
// Get a reference to the root node
XmlElement elmRoot = xmlDoc.DocumentElement;
// Create a list of the videos
XmlNodeList lstVideos = xmlDoc.GetElementsByTagName("video");
// visit each video
foreach (XmlNode node in lstVideos)
{
// Within a video, get a list of its children
XmlNodeList lstChildren = node.ChildNodes;
// Visit each child node
foreach (XmlNode dir in lstChildren)
{
// If the child node is Bruce Beresford
if (dir.InnerText == "Adrian Lyne")
{
node.RemoveChild(dir);
// Save the file
xmlDoc.Save(Filename);
// Stop
break;
}
}
}
}
}
|
Clearing an Element of its Children |
|
To delete all child nodes of a node, you can call the XmlNode.RemoveAll()
method. Its syntax is:
public virtual void RemoveAll();
When called, this method will remove all child nodes, if
any, of their parent node.
|
|