Introduction to XML Elements
Introduction to XML Elements
The Child Nodes of a Node
Introduction
As mentioned already, one node can be nested inside of another. A nested node is called a child of the nesting node. This also implies that a node can have as many children as necessary, making them child nodes of the parent node. Once again, consider our Videos.xml example:
<?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 Mins</length> <format>DVD</format> <rating>PG-13</rating> </video> <video> <title>Chalte Chalte</title> <director>Aziz Mirza</director> <length>145 Mins</length> <format>DVD</format> <rating>N/R</rating> </video> </videos>
The title and the director nodes are children of the video node. The video node is the parent of both the title and the director nodes.
Practical Learning: Introducing Child Nodes
body { background-color: #2b5b8f; } .top-bar { top: 0px; width: 100%; position: fixed; height: 6.85em; background-color: #203864; } .containment { margin: auto; width: 460px; } .navbar-inverse { background-color: #001132; border-top: 3px solid #cfdde0; border-bottom: 3px solid #cfdde0; } .navbar-fixed-top { top: 6.75em; } .jumbotron { padding-bottom: 4px; background-color: #153a62; } .col-md-3 h2 { color: #abcbd9; border-bottom: 1px solid #cfdde0; } .lead { color: #cfdde0; } .col-md-3 p { color: #d5d4c2; } .caption { color: aliceblue; } .copyright { color: #beeeab; } .push-down { margin-top: 8em; } .push-down h2 { font-weight: 600; font-size: 26px; text-align: center; color: #d5d4c2; font-family: Garamond, Georgia, 'Times New Roman', serif; } .push-down h3 { color: #abcbd9; } .push-down p { color: #cfdde0; } .water-nav { text-decoration: none; color: yellow; } .water-nav:link { color: orange; } .water-nav:visited { color: aliceblue; } .water-nav:active { color: #a8c3ce; } .water-nav:hover { color: yellow; } .common-font { font-family: Garamond, Georgia, 'Times New Roman', serif; } .table-striped > tbody > tr:nth-of-type(even) { color: navy; background-color: azure; } .table-striped > tbody > tr:nth-of-type(odd) { color: aliceblue; background-color: cornflowerblue; }
using System.Web.Optimization;
namespace WaterDistribution2
{
public class BundleConfig
{
// For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at https://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css",
"~/Content/WaterDistribution.css"));
}
}
}
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - Water for a Shining Life</title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="top-bar"> <div class="containment"><img src="~/Images/wsl1.png" alt="Water for a Shining Life" width="490" height="92" /></div> </div> <div class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> @Html.ActionLink("Water Distribution Company", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("Emergency Services", "Index", "Home")</li> <li>@Html.ActionLink("Cummunity", "Index", "Home")</li> <li>@Html.ActionLink("Environment", "Index", "Home")</li> <li>@Html.ActionLink("Customer Service", "Index", "Home")</li> <li>@Html.ActionLink("Employment", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Contact", "Contact", "Home")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p class="copyright text-center common-font">© @DateTime.Now.Year - Water for a Shining Life</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
A Collection of XML Nodes
As you may know already, an XML document usually contains many nodes. To consider a collection of nodes, the .NET Framework provides a collection class named XmlNodeList. It starts as follows:
public abstract class XmlNodeList : IEnumerable, IDisposable
Linking the Nodes
To manage the relationships among the nodes of an XML document, the .NET Framework provides a class named XmlLinkedNode:
public abstract class XmlLinkedNode : XmlNode
As a result, many classes derive from XmlLinkedNode. That's the case for the XmlElement class:
public class XmlElement : XmlLinkedNode
A Collection of Child Nodes
To support the child nodes of a particular node, the XmlNode class is equipped with a property named ChildNodes. That property is of type XmlNodeList. The property is declared as follows:
public virtual XmlNodeList ChildNodes { get; }
When this property is used, it produces an XmlNodeList list, which is a collection of all nodes that share the same parent. Each item in the collection is of type XmlNode. To give you the number of nodes on an XmlNodeList collection, the class is equipped with a property named Count. Here is an example of using it:
@{
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();
string strVideosFile = Server.MapPath("~/App_Data/Videos.xml");
if (File.Exists(strVideosFile))
{
xdVideos.Load(strVideosFile);
System.Xml.XmlElement xeVideo = xdVideos.DocumentElement;
System.Xml.XmlNodeList xnlVideos = xeVideo.ChildNodes;
<p>The root element contains @xnlVideos.Count nodes.</p>
}
}
This would produce:
You can also use the Count property in a loop (while, do...while, or for) to visit the members of the collection.
Practical Learning: Getting a Collection of Child Nodes
using System; using System.IO; using System.Xml; using System.Web.Mvc; namespace WaterDistribution2.Controllers { public class CustomersController : Controller { // GET: Customers public ActionResult Index() { // Get a reference to the XML DOM XmlDocument xdCustomers = new XmlDocument(); // This is the name and path of the XML file that contains the customers records string strFileCustomers = Server.MapPath("/WaterDistribution/Customers.xml"); // If a file that contains the customers records was previously created, ... if (System.IO.File.Exists(strFileCustomers)) { // ... open it using (FileStream fsCustomers = new FileStream(strFileCustomers, FileMode.Open, FileAccess.Read, FileShare.Read)) { // and store the records in the DOM xdCustomers.Load(fsCustomers); } /* If the Customers records exist, send them to the view. * If there is no file for the customers, indicate that the DOM is null. */ ViewBag.customers = xdCustomers.DocumentElement.ChildNodes.Count > 0 ? xdCustomers.DocumentElement.ChildNodes : null; } return View(); } . . . No Change } }
using System; using System.Collections.Generic; using System.IO; using System.Xml; using System.Web.Mvc; namespace WaterDistribution2.Controllers { public class WaterMetersController : Controller { // GET: WaterMeters public ActionResult Index() { XmlDocument xdWaterMeters = new XmlDocument(); string strFileWaterMeters = Server.MapPath("/WaterDistribution/WaterMeters.xml"); if (System.IO.File.Exists(strFileWaterMeters)) { using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdWaterMeters.Load(fsWaterMeters); } if (xdWaterMeters.DocumentElement.ChildNodes.Count > 0) { ViewBag.waterMeters = xdWaterMeters.DocumentElement.ChildNodes; } else { ViewBag.waterMeters = null; } } return View(); } . . . No Change } }
Accessing a Node in a Collection
The children of a node, that is, the members of a ChildNodes property, or the members of an XmlNodeList collection, can be located each by an index. The first node has an index of 0, the second has an index of 1, and so on. To give you access to a node of the collection, the XmlNodeList class is equipped with an indexed property and a method named Item. Both produce the same result. For example, if a node has three children, to access the third, you can apply an index of 2 to its indexed property. Here is an example:
@{
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();
string strVideosFile = Server.MapPath("~/App_Data/Videos.xml");
if (File.Exists(strVideosFile))
{
xdVideos.Load(strVideosFile);
System.Xml.XmlElement xeVideo = xdVideos.DocumentElement;
System.Xml.XmlNodeList xnlVideos = xeVideo.ChildNodes;
<p>@xnlVideos[2].InnerText</p>
}
}
You can also use the Item() method to get the same result. Using a loop (while, do...while, or for), you can access each node and display the values of its children as follows:
@{ System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeVideo = xdVideos.DocumentElement; System.Xml.XmlNodeList xnlVideos = xeVideo.ChildNodes; <ul> @for (int i = 0; i < xnlVideos.Count; i++) { <li>@xnlVideos[i].InnerText</li> } </ul> } }
Instead of using the indexed property, the XmlNodeList class implements the IEnumerable interface. This allows you to use a foreach loop to visit each node of the collection. Here is an example:
@{ System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeVideo = xdVideos.DocumentElement; System.Xml.XmlNodeList xnlVideos = xeVideo.ChildNodes; <ul> @foreach (System.Xml.XmlNode node in xnlVideos) { <li>@node.InnerText</li> } </ul> } }
To better manage and manipulate the nodes of a collection of nodes, you must be able to access the desired node. The XmlNode class combined with the XmlNodeList class provide various means of getting to a node and taking the appropriate actions.
The Parent of a Node
Not all nodes have children, obviously. For example, the title node of our Videos.xml file doesn't have children. To find out whether a node has children, check its HasChildNodes Boolean property that is declared as follows:
public virtual bool HasChildNodes { get; }
If a node is a child, to get its parent, you can access a property named ParentNode.
Fundamentals of Element Creation
Introduction
As seen so far, to create an XML element, you can directly type the XML code in a document. When the file is saved, it is ready to be processed. In some applications, you will want the user to provide you with the necessary value(s) to create an element. Fortunately, the XmlDocument, the XmlNode, and the XmlElement classes provide all the necessary properties and methods to perform the routine operations of an XML file, an element, or a node. The primary operation consists of creating a new element or a node.
Before performing an operation, you will usually need to decide in what section of the file you want the action to be applied. As it happens, you have the root node, a particular node inside the document, parent of a node, the sibling of a node, etc. To get to a node, you will usually first get a reference to its XmlElement. To do this, you can declare an XmlElement variable and initialize it with that reference.
Appending an Element
To let you add an element to an XML document, the XmlNode class, which is the ancestor of all XML nodes of the .NET Framework, provides a method named AppendChild. Its syntax is:
public virtual XmlNode AppendChild(XmlNode newChild);
Calling this method an XmlElement object.
Adding a Value to the Root Node
Consider an XML file named Studies.xml that starts as follows:
<?xml version="1.0" encoding="utf-8" ?> <studies></studies>
To let you add something, such as a value, to the root node the XmlDocument class provides a method named CreateTextNode. This method returns an XmlText value. The syntax of this method is:
public virtual XmlText CreateTextNode(string text);
This method takes as argument the string that would constitute the value of the element. Before calling it, you should have used the XmlNode.AppendChild() method to create a node. Here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Studies</title>
</head>
<body>
@{
string strXMLFile = Server.MapPath("~/App_Data/Studies.xml");
System.Xml.XmlDocument xdStudies = new System.Xml.XmlDocument();
xdStudies.Load(strXMLFile);
System.Xml.XmlElement xeRoot = xdStudies.DocumentElement;
System.Xml.XmlText xtNursing = xdStudies.CreateTextNode("Nursing Studies - Curriculum");
xeRoot.AppendChild(xtNursing);
xdStudies.Save(strXMLFile);
}
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<studies>Nursing Studies - Curriculum</studies>
Adding an Empty Element to the Root
To assist you with programmatically creating a new element, the XmlDocument class is equipped with a method named CreateElement. It is overloaded with three versions. One of the versions uses the following syntax:
public XmlElement CreateElement(string name);
To create a new element, call this method and pass the name of the new element to it. For example, imagine you want to add a new Title element to the above file. You would start with code as follows:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("Title"); } }
After calling the CreateElement method, call the XmlDocument.AppendChild() method to add the new element to the root node. Here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Video Collection</title>
</head>
<body>
@{
string strVideosFile = Server.MapPath("~/App_Data/Videos.xml");
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();
if (File.Exists(strVideosFile))
{
xdVideos.Load(strVideosFile);
System.Xml.XmlElement xeRoot = xdVideos.DocumentElement;
System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("title");
xeRoot.AppendChild(xeNewVideo);
}
else
{
// Create the default XML structure
xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<videos></videos>");
}
xdVideos.Save(strVideosFile);
}
</body>
</html>
Adding a Full Element to the Root
Consider a starting XML file named Studies.xml:
<?xml version="1.0" encoding="utf-8"?> <studies> </studies>
We know (from the previous lesson) that the XmlNode class is equipped with the InnerXml property that holds a whole XML element. To add a new element to the root node, create the whole markup of the node. If necessary, include its child(ren) with its (their) markup(s) as a string and assign that string to an XmlNode.InnerXml string. Here is an example of using this property:
<!DOCTYPE html>
<html>
<head>
<title>Video Collection</title>
</head>
<body>
@{
string strStudies = Server.MapPath("~/App_Data/Studies.xml");
System.Xml.XmlDocument xdStudies = new System.Xml.XmlDocument();
if (File.Exists(strStudies))
{
using(FileStream fsStudies = new FileStream(strStudies, FileMode.Open, FileAccess.Read, FileShare.Read))
{
xdStudies.Load(fsStudies);
}
System.Xml.XmlElement xeVideo = xdStudies.CreateElement("degrees");
string strNewvideo = "<undergraduate>Bachelor of Science in Nursing (BSN)</undergraduate>" +
"<graduate>Master of Science in Nursing (MSN)</graduate>" +
"<doctoral>Doctor of Nursing Practice (DNP)</doctoral>";
xeVideo.InnerXml = strNewvideo;
xdStudies.DocumentElement.AppendChild(xeVideo);
using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
{
xdStudies.Save(fsStudies);
}
}
}
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<studies>
<degrees>
<undergraduate>Bachelor of Science in Nursing (BSN)</undergraduate>
<graduate>Master of Science in Nursing (MSN)</graduate>
<doctoral>Doctor of Nursing Practice (DNP)</doctoral>
</degrees>
</studies>
Once again, consider a starting XML file named Studies.xml:
<?xml version="1.0" encoding="utf-8"?> <studies> </studies>
Practical Learning: Introducing Element Creation
using System; using System.Collections.Generic; using System.IO; using System.Xml; using System.Web.Mvc; namespace WaterDistribution2.Controllers { public class WaterMetersController : Controller { // GET: WaterMeters public ActionResult Index() { XmlDocument xdWaterMeters = new XmlDocument(); string strFileWaterMeters = Server.MapPath("/WaterDistribution/WaterMeters.xml"); if (System.IO.File.Exists(strFileWaterMeters)) { using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdWaterMeters.Load(fsWaterMeters); } if (xdWaterMeters.DocumentElement.ChildNodes.Count > 0) { ViewBag.waterMeters = xdWaterMeters.DocumentElement.ChildNodes; } else { ViewBag.waterMeters = null; } } return View(); } . . . No Change // GET: WaterMeters/Create public ActionResult Create() { return View(); } // POST: WaterMeters/Create [HttpPost] public ActionResult Create(FormCollection collection) { try { // TODO: Add insert logic here XmlDocument xdWaterMeters = new XmlDocument(); string strFileWaterMeters = Server.MapPath("/WaterDistribution/WaterMeters.xml"); // Make sure a meter number was provided. If not, don't do nothing if (!string.IsNullOrEmpty(collection["MeterNumber"])) { // If an XML file for water meters was created already, ... if (System.IO.File.Exists(strFileWaterMeters)) { // ... open it ... using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { // ... and put the records in the DOM xdWaterMeters.Load(fsWaterMeters); } } else { // If there no XML file yet, create skeleton code for an XML document xdWaterMeters.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<water-meters></water-meters>"); } // Get ready to create an XML element named water-meter XmlElement xeWaterMeter = xdWaterMeters.CreateElement("water-meter"); // Create the markup of the XML water meter string strWaterMeter = "<meter-number>" + collection["MeterNumber"] + "</meter-number>" + "<make>" + collection["Make"] + "</make>" + "<model>" + collection["Model"] + "</model>" + "<meter-size>" + collection["MeterSize"] + "</meter-size>" + "<date-last-update>" + collection["DateLastUpdate"] + "</date-last-update>" + "<counter-value>" + collection["CounterValue"] + "</counter-value>"; // Specify the markup of the new element xeWaterMeter.InnerXml = strWaterMeter; // Add the new node to the root xdWaterMeters.DocumentElement.AppendChild(xeWaterMeter); // Save the (new version of the) XML file using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.Create, FileAccess.Write, FileShare.Write)) { xdWaterMeters.Save(fsWaterMeters); } } /* Since the XML file has been created or updated, send the user back to the list of water meters. */ return RedirectToAction("Index"); } catch { return View(); } } // GET: WaterMeters/Edit/5 public ActionResult Edit(int id) { return View(); } . . . No Change } }
@{ ViewBag.Title = "New Water Meter"; } <div class="push-down"> <h2>New Water Meter</h2> </div> <hr /> @using (Html.BeginForm()) { <div class="form-horizontal"> <div class="form-group"> <label for="mtrNbr" class="control-label col-md-4 caption">Meter #:</label> <div class="col-md-8"> @Html.TextBox("MeterNumber", null, htmlAttributes: new { @class = "form-control", id = "mtrNbr" }) </div> </div> <div class="form-group"> <label for="make" class="control-label col-md-4 caption">Make:</label> <div class="col-md-8"> @Html.TextBox("Make", null, htmlAttributes: new { @class = "form-control", id = "make" }) </div> </div> <div class="form-group"> <label for="model" class="control-label col-md-4 caption">Model:</label> <div class="col-md-8"> @Html.TextBox("Model", null, htmlAttributes: new { @class = "form-control", id = "model" }) </div> </div> <div class="form-group"> <label for="mtrSize" class="control-label col-md-4 caption">Meter Size:</label> <div class="col-md-8"> @Html.TextBox("MeterSize", null, htmlAttributes: new { @class = "form-control", id = "mtrSize" }) </div> </div> <div class="form-group"> <label for="dlu" class="control-label col-md-4 caption">Date Last Update:</label> <div class="col-md-8"> @Html.TextBox("DateLastUpdate", null, htmlAttributes: new { @class = "form-control", type = "date", id = "dlu" }) </div> </div> <div class="form-group"> <label for="cntVal" class="control-label col-md-4 caption">Counter Value:</label> <div class="col-md-8"> @Html.TextBox("CounterValue", null, htmlAttributes: new { @class = "form-control", id = "cntVal" }) </div> </div> <div class="form-group"> <label class="control-label col-md-5"> @Html.ActionLink("Water Meters", "Index", null, htmlAttributes: new { @class = "water-nav" }) </label> <div class="col-md-7"> <input type="submit" value="Create Water Meter" class="btn btn-primary" /> </div> </div> </div> }
Adding an Element with Sub-Elements
You can create an element that has child elements that themselves have child elements. Here is an example:
<!DOCTYPE html>
<html>
<head>
<title>Video Collection</title>
</head>
<body>
@{
string strStudies = Server.MapPath("~/App_Data/Studies.xml");
System.Xml.XmlDocument xdStudies = new System.Xml.XmlDocument();
if (File.Exists(strStudies))
{
using(FileStream fsStudies = new FileStream(strStudies, FileMode.Open, FileAccess.Read, FileShare.Read))
{
xdStudies.Load(fsStudies);
}
System.Xml.XmlElement xeStudy = xdStudies.CreateElement("freshman");
string strNursingProgram = "<fall-term><course>Human Anatomy & Physiology I</course>" +
"<course>Introduction to Practice-Based Research I</course>" +
"<course>English Composition for Health Professions</course>" +
"<course>Infant Psychology</course>" +
"<course>Introduction to Expressive Sociology</course></fall-term>" +
"<spring><course>Introduction to Statistics in Health Care</course>" +
"<course>Human Anatomy & Physiology II</course>" +
"<course>Microbiology I</course></spring>";
xeStudy.InnerXml = strNursingProgram;
xdStudies.DocumentElement.AppendChild(xeStudy);
using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
{
xdStudies.Save(fsStudies);
}
}
}
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<studies>
<freshman>
<fall-term>
<course>Human Anatomy & Physiology I</course>
<course>Introduction to Practice-Based Research I</course>
<course>English Composition for Health Professions</course>
<course>Infant Psychology</course>
<course>Introduction to Expressive Sociology</course>
</fall-term>
<spring>
<course>Introduction to Statistics in Health Care</course>
<course>Human Anatomy & Physiology II</course>
<course>Microbiology I</course>
</spring>
</freshman>
</studies>
Suppose that a document already contains one or more elements. Here is example of a 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> </videos>
To add a new element as a child of the root, "build" one or all child elements, then assign the element to the XmlNode.InnerXml property. Here is an example:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeVideo = xdVideos.CreateElement("video"); string strNewvideo = "<title>Other People's Money</title>" + "<director>Alan Brunstein</director>" + "<length>114 Minutes</length>" + "<format>VHS</format>" + "<rating>PG-13</rating>"; xeVideo.InnerXml = strNewvideo; xdVideos.DocumentElement.AppendChild(xeVideo); } else { // Create the default XML structure xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<videos></videos>"); } xdVideos.Save(strVideosFile); }
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>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 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>
The Last Child Node
Introduction
The child node that immediately precedes the end-tag of the parent node is called the last child. To give you access to the last child of a node, the XmlNode class is equipped with a property named LastChild. It is declared as follows:
public virtual XmlNode LastChild { get; }
Appending a Last Element
We saw that, to create a new element, the XmlDocument class provides the overloaded CreateElement() method. To add the new element to a file, you must specify its position in the tree. For example, you may want the new element to be positioned as the last node.
To support the positions of existing nodes, the XmlNode class, which is the ancestor of all XML nodes of the .NET Framework, provides various methods, including the AppendChild method that we saw already. It is used to add an element as the last child of its parent. Normally, when you add an element to the root node, the new element is added as the last. An alternative is to call the LastChild property of the root node. As a result, the following code:
<!DOCTYPE html>
<html>
<head>
<title>Video Collection</title>
</head>
<body>
@{
string strStudies = Server.MapPath("~/App_Data/Studies.xml");
System.Xml.XmlDocument xdStudies = new System.Xml.XmlDocument();
if (File.Exists(strStudies))
{
using(FileStream fsStudies = new FileStream(strStudies, FileMode.Open, FileAccess.Read, FileShare.Read))
{
xdStudies.Load(fsStudies);
}
System.Xml.XmlElement xeStudy = xdStudies.CreateElement("sophomore");
string strNursingProgram = "<fall-term><course>Foundations of Pathology</course>" +
"<course>Computer Databases I</course>" +
"<course>Human Anatomy & Physiology III</course>" +
"<course>Infant Psychology II</course>" +
"<course>Pharmacology I</course></fall-term>" +
"<spring><course>Foundations of Clinical Nursing</course>" +
"<course>Desktop Applications</course>" +
"<course>Microbiology II</course></spring>";
xeStudy.InnerXml = strNursingProgram;
xdStudies.DocumentElement.AppendChild(xeStudy);
using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
{
xdStudies.Save(fsStudies);
}
}
}
</body>
</html>
is the same as:
<!DOCTYPE html>
<html>
<head>
<title>Video Collection</title>
</head>
<body>
@{
string strStudies = Server.MapPath("~/App_Data/Studies.xml");
System.Xml.XmlDocument xdStudies = new System.Xml.XmlDocument();
if (File.Exists(strStudies))
{
using(FileStream fsStudies = new FileStream(strStudies, FileMode.Open, FileAccess.Read, FileShare.Read))
{
xdStudies.Load(fsStudies);
}
System.Xml.XmlElement xeStudy = xdStudies.CreateElement("sophomore");
string strNursingProgram = "<fall-term><course>Foundations of Pathology</course>" +
"<course>Computer Databases I</course>" +
"<course>Human Anatomy & Physiology III</course>" +
"<course>Infant Psychology II</course>" +
"<course>Pharmacology I</course></fall-term>" +
"<spring><course>Foundations of Clinical Nursing</course>" +
"<course>Desktop Applications</course>" +
"<course>Microbiology II</course></spring>";
xeStudy.InnerXml = strNursingProgram;
xdStudies.DocumentElement.LastChild.AppendChild(xeStudy);
using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
{
xdStudies.Save(fsStudies);
}
}
}
</body>
</html>
Adding an Element to the Last Child Node
Consider an XML file named Studies.xml that has the following content:
<?xml version="1.0" encoding="utf-8"?> <studies> <nursing> </nursing> <mechanical-engineering> <freshman> <fall> <course>Physics I</course> <course>General Chemistry</course> </fall> <spring> <course>Integral Calculus</course> <course>Computing for Engineers</course> </spring> </freshman> <sophomore></sophomore> </mechanical-engineering> </studies>
To add a new element as a child of the last node of a document, you can access the LastChild property of the LastChild of the root node. Of course, make sure you Call the AppendChild() method of the root node. Here is an example:
<!DOCTYPE html> <html> <head> <title>Video Collection</title> </head> <body> @{ string strStudies = Server.MapPath("~/App_Data/Studies.xml"); System.Xml.XmlDocument xdStudies = new System.Xml.XmlDocument(); if (File.Exists(strStudies)) { using(FileStream fsStudies = new FileStream(strStudies, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdStudies.Load(fsStudies); } System.Xml.XmlElement xeStudy = xdStudies.CreateElement("fall"); string strNursingProgram = "<course>Multivariable Calculus I</course>" + "<course>Differential Equations I</course>" + "<course>Computing Techniques</course>" + "<course>Dynamics of Rigid Bodies</course>"; xeStudy.InnerXml = strNursingProgram; xdStudies.DocumentElement.LastChild.LastChild.AppendChild(xeStudy); using (FileStream fsStudies = new FileStream(strStudies, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write)) { xdStudies.Save(fsStudies); } } } </body> </html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<studies>
<nursing>
</nursing>
<mechanical-engineering>
<freshman>
<fall>
<course>Physics I</course>
<course>General Chemistry</course>
</fall>
<spring>
<course>Integral Calculus</course>
<course>Computing for Engineers</course>
</spring>
</freshman>
<sophomore>
<fall>
<course>Multivariable Calculus I</course>
<course>Differential Equations I</course>
<course>Computing Techniques</course>
<course>Dynamics of Rigid Bodies</course>
</fall>
</sophomore>
</mechanical-engineering>
</studies>
Consider the following XML file named "videos.xml":
<?xml version="1.0" encoding="utf-8"?> <videos> <video> <title>The Distinguished Gentleman</title> </video> <video> <title>Basic Instinct</title> </video> </videos>
Notice that the root, videos, has a repetitive child named video. This video child has its own child named Title. Imagine that you want to add a new video node that has a child. To do this, first create an empty video node as a child of the root. We learned earlier how to do that:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("video"); xeRoot.AppendChild(xeNewVideo); } else { xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<videos></videos>"); } xdVideos.Save(strVideosFile); }
After creating the new child of the root, initialize the grand child with the desired name (the name doesn't have to be one of the existing names) and a value (which is optional if you don't want the new node to have a value). Once the new node is ready, append it as the last child of the root. If this new node has a value, append its XmlText object as the LastChild of the LastChild of the root. Here is an example of how you would do this:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("video"); xeRoot.AppendChild(xeNewVideo); xeRoot = xdVideos.DocumentElement; xeNewVideo = xdVideos.CreateElement("title"); System.Xml.XmlText xtVideo = xdVideos.CreateTextNode("Her Alibi"); xeRoot.LastChild.AppendChild(xeNewVideo); xeRoot.LastChild.LastChild.AppendChild(xtVideo); } else { xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<videos></videos>"); } xdVideos.Save(strVideosFile); }
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
</video>
<video>
<title>Basic Instinct</title>
</video>
<video>
<title>Her Alibi</title>
</video>
</videos>
Now consider the following 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> </videos>
The root, videos, has a child node named video. The video node has many child nodes. By now, we know how to add a child to the root. We also saw how to add a grand child with value to the root. To add many (grand) children to a node, first build the node, add it to the root, then continuously add the necessary nodes, one at a time, including its name and its optional value. This can be done as follows:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("video"); xeRoot.AppendChild(xeNewVideo); xeRoot = xdVideos.DocumentElement; xeNewVideo = xdVideos.CreateElement("title"); System.Xml.XmlText xtVideo = xdVideos.CreateTextNode("The Day After Tomorrow"); xeRoot.LastChild.AppendChild(xeNewVideo); xeRoot.LastChild.LastChild.AppendChild(xtVideo); xeNewVideo = xdVideos.CreateElement("director"); xtVideo = xdVideos.CreateTextNode("Roland Emmerich"); xeRoot.LastChild.AppendChild(xeNewVideo); xeRoot.LastChild.LastChild.AppendChild(xtVideo); xeNewVideo = xdVideos.CreateElement("length"); xtVideo = xdVideos.CreateTextNode("124 Minutes"); xeRoot.LastChild.AppendChild(xeNewVideo); xeRoot.LastChild.LastChild.AppendChild(xtVideo); xeNewVideo = xdVideos.CreateElement("format"); xtVideo = xdVideos.CreateTextNode("DVD"); xeRoot.LastChild.AppendChild(xeNewVideo); xeRoot.LastChild.LastChild.AppendChild(xtVideo); xeNewVideo = xdVideos.CreateElement("rating"); xtVideo = xdVideos.CreateTextNode("PG-13"); xeRoot.LastChild.AppendChild(xeNewVideo); xeRoot.LastChild.LastChild.AppendChild(xtVideo); } else { xdVideos.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<videos></videos>"); } xdVideos.Save(strVideosFile); }
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>
</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>
</videos>
Using the same approach, you can add children to children of children, and so on.
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:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); // Get a reference to the root node System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; // Create a list of nodes whose name is Title System.Xml.XmlNodeList xnlTitles = xdVideos.GetElementsByTagName("title"); // Now you can check each node of the list foreach (System.Xml.XmlNode node in xnlTitles) { // 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 System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("category"); // Create the text of the new element System.Xml.XmlText txtCatetory = xdVideos.CreateTextNode("Comedy"); // Get a reference to the parent of the node we have found System.Xml.XmlNode elmParent = node.ParentNode; // Add the new element to the node we found elmParent.AppendChild(xeNewVideo); // Specify the text of the new node elmParent.LastChild.AppendChild(txtCatetory); // Save the file xdVideos.Save(strVideosFile); } } } }
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:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); // Get a reference to the root node System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; // Create a list of nodes whose name is Title System.Xml.XmlNodeList xnlTitles = xdVideos.GetElementsByTagName("title"); // Now you can check each node of the list foreach (System.Xml.XmlNode node in xnlTitles) { // 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 System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("actors"); // Get a reference to the parent of the node we have found System.Xml.XmlNode elmVideo = node.ParentNode; // Add the new element to the node we found elmVideo.AppendChild(xeNewVideo); // Create an element as a child of the new element // Specify its name as Actor xeNewVideo = xdVideos.CreateElement("actor"); // Create the text of the new element System.Xml.XmlText txtActor = xdVideos.CreateTextNode("Dennis Quaid"); // Add the new Actor element to the Actors node elmVideo.LastChild.AppendChild(xeNewVideo); // Specify the text of the new node elmVideo.LastChild.LastChild.AppendChild(txtActor); // In the same way, add the other Actor nodes xeNewVideo = xdVideos.CreateElement("actor"); txtActor = xdVideos.CreateTextNode("Jake Gyllenhaal"); elmVideo.LastChild.AppendChild(xeNewVideo); elmVideo.LastChild.LastChild.AppendChild(txtActor); xeNewVideo = xdVideos.CreateElement("actor"); txtActor = xdVideos.CreateTextNode("Emmy Rossum"); elmVideo.LastChild.AppendChild(xeNewVideo); elmVideo.LastChild.LastChild.AppendChild(txtActor); xeNewVideo = xdVideos.CreateElement("actor"); txtActor = xdVideos.CreateTextNode("Dash Mihok"); elmVideo.LastChild.AppendChild(xeNewVideo); elmVideo.LastChild.LastChild.AppendChild(txtActor); // Save the file xdVideos.Save(strVideosFile); } } } }
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:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); // Get a reference to the root node System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; // Create a list of nodes whose name is Title System.Xml.XmlNodeList xnlTitles = xdVideos.GetElementsByTagName("title"); // Now you can check each node of the list foreach (System.Xml.XmlNode node in xnlTitles) { // 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 System.Xml.XmlNode xeVideo = node.ParentNode; // Create a list of the child nodes of the Her alibi video System.Xml.XmlNodeList xnlActors = xeVideo.ChildNodes; // Visit each item of the collection // looking for an element named Actors foreach (System.Xml.XmlNode nodActor in xnlActors) { // If you find an element named Actors if (nodActor.Name == "actors") { // Create a new element named Actor // Specify its name as Actor System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("actor"); // Create the text of the new element System.Xml.XmlText txtActor = xdVideos.CreateTextNode("Tom Selleck"); // Add the new Actor element to the Actors node xeVideo.LastChild.AppendChild(xeNewVideo); // Specify the text of the new node xeVideo.LastChild.LastChild.AppendChild(txtActor); // Add other Actor nodes xeNewVideo = xdVideos.CreateElement("actor"); txtActor = xdVideos.CreateTextNode("Paulina Porizkova"); xeVideo.LastChild.AppendChild(xeNewVideo); xeVideo.LastChild.LastChild.AppendChild(txtActor); xeNewVideo = xdVideos.CreateElement("actor"); txtActor = xdVideos.CreateTextNode("William Daniels"); xeVideo.LastChild.AppendChild(xeNewVideo); xeVideo.LastChild.LastChild.AppendChild(txtActor); // Save the file xdVideos.Save(strVideosFile); // 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>
The First Child Node
Introduction
In a typical XML document, the first line is called the first child of the DOM. This would be:
<?xml version="1.0" encoding="utf-8"?>
After identifying or locating a node, the first node that immediately follows it is referred to as its first child.
Adding an Element as the First Child
Consider the following document saved in a 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> </videos>
To let you add a new element and position it as the first in an XML document, the XmlNode class is equipped with a method named PrependChild. Its syntax is:
public virtual XmlNode PrependChild(XmlNode newChild);
This method receives an argument as an XmlNode object and adds it on top of the XML document. Here is an example of calling it:
@{
string strVideosFile = Server.MapPath("~/App_Data/Videos.xml");
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();
if (File.Exists(strVideosFile))
{
xdVideos.Load(strVideosFile);
System.Xml.XmlElement xeRoot = xdVideos.DocumentElement;
System.Xml.XmlElement xeVideo = xdVideos.CreateElement("video");
// Specify the child nodes of the element
xeVideo.InnerXml = "7243 4 92525 9 2" +
"<title>Yanni - Tribute</title>" +
"<director>George Veras</director>" +
"<format>DVD</format>";
// Add the new element as the first node in the document
xeRoot.PrependChild(xeVideo);
xdVideos.Save(strVideosFile);
}
}
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<Video>7243 4 92525 9 2
<title>Yanni - Tribute</title>
<director>George Veras</director>
<format>DVD</format>
</Video>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
</videos>
Practical Learning: Creating an Element as the First Child of the Root
using System; using System.Collections.Generic; using System.IO; using System.Xml; using System.Web.Mvc; namespace WaterDistribution2.Controllers { public class CustomersController : Controller { . . . No Change // GET: Customers/Create public ActionResult Create() { return View(); } // POST: Customers/Create [HttpPost] public ActionResult Create(FormCollection collection) { try { // TODO: Add insert logic here ViewBag.ErrorMessage = ""; bool meterNumberIsValid = false; XmlDocument xdWaterMeters = new XmlDocument(); XmlDocument xdCustomersAccounts = new XmlDocument(); string strFileCustomers = Server.MapPath("/WaterDistribution/Customers.xml"); string strFileWaterMeters = Server.MapPath("/WaterDistribution/WaterMeters.xml"); // Make sure the user provides an account number, ... if (!string.IsNullOrEmpty(collection["AccountNumber"])) { // If the user provided an account number, to start, find out if a file for water meters was created already. if (System.IO.File.Exists(strFileWaterMeters)) { // If a file for water meters exists, open it using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Store the list of water meters in an XML document xdWaterMeters.Load(fsWaterMeters); // Create a list of child nodes of the root node XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement.ChildNodes; // Visit each node of the list of elements foreach (XmlNode xnWaterMeter in xnlWaterMeters) { // When you get to a list of (child) nodes of a water-meter node, visit each child node foreach (XmlNode xnMeterNumber in xnWaterMeter.ChildNodes) { // If you find a meter number that is the same as the meter number from the form, ... if (xnMeterNumber.InnerText == collection["MeterNumber"]) { // ... make a note meterNumberIsValid = true; } } } } } // If either the user didn't provide a meter number or provided a meter number that doesn't exist, ... if (meterNumberIsValid == false) { // ... create a message that will display to the user ViewBag.ErrorMessage = "You must provide a valid meter number"; } else { // It appears that the user provided both an account number and a valid meter number. // If an XML file for customers accounts was previously created, ... if (System.IO.File.Exists(strFileCustomers)) { // ... open it ... using (FileStream fsCustomers = new FileStream(strFileCustomers, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { // ... and put the records in the DOM xdCustomersAccounts.Load(fsCustomers); } } else { // If there is no XML file yet for the customers, create skeleton code for an XML document xdCustomersAccounts.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<customers></customers>"); } // Get ready to create an XML element named customer XmlElement xeCustomer = xdCustomersAccounts.CreateElement("customer"); // Create the markup of the XML customer string strCustomer = "<account-number>" + collection["AccountNumber"] + " </account-number>" + "<meter-number>" + collection["MeterNumber"] + " </meter-number>" + "<first-name>" + collection["FirstName"] + " </first-name>" + "<last-name>" + collection["LastName"] + " </last-name>" + "<address>" + collection["Address"] + " </address>" + "<city>" + collection["City"] + " </city>" + "<county>" + collection["County"] + " </county>" + "<state>" + collection["State"] + " </state>" + "<zip-code>" + collection["ZIPCode"] + " </zip-code>"; // Specify the markup of the new element xeCustomer.InnerXml = strCustomer; // Add the new node to the root xdCustomersAccounts.DocumentElement.PrependChild(xeCustomer); // Save the (new version of the) XML file using (FileStream fsCustomers = new FileStream(strFileCustomers, FileMode.Create, FileAccess.Write, FileShare.Write)) { xdCustomersAccounts.Save(fsCustomers); } } } else { // ... prepare a message that will be sent to the user ViewBag.ErrorMessage = "You must provide both a customer account number and a valid water meter number."; } return RedirectToAction("Index"); } catch { return View(); } } . . . No Change } }
@{ ViewBag.Title = "New Customer Account"; } <div class="push-down"> <h2>New Customer Account</h2> </div> <hr /> @using (Html.BeginForm()) { <div class="form-horizontal"> <div class="form-group"> <label for="acntNbr" class="control-label col-md-4 caption">Account #:</label> <div class="col-md-8"> @Html.TextBox("AccountNumber", null, htmlAttributes: new { @class = "form-control", id = "acntNbr" }) </div> </div> <div class="form-group"> <label for="mtrNbr" class="control-label col-md-4 caption">Water Meter:</label> <div class="col-md-8"> @Html.TextBox("MeterNumber", null, htmlAttributes: new { @class = "form-control", id = "mtrNbr" }) </div> </div> <div class="form-group"> <label class="control-label col-md-4 caption"> </label> <div class="col-md-8"><input type="text" id="meterDetails" class="form-control" disabled /></div> </div> <div class="form-group"> <label for="fName" class="control-label col-md-4 caption">First Name:</label> <div class="col-md-8"> @Html.TextBox("FirstName", null, htmlAttributes: new { @class = "form-control", id = "fName" }) </div> </div> <div class="form-group"> <label for="lName" class="control-label col-md-4 caption">Last Name:</label> <div class="col-md-8"> @Html.TextBox("LastName", null, htmlAttributes: new { @class = "form-control", id = "lName" }) </div> </div> <div class="form-group"> <label for="adrs" class="control-label col-md-4 caption">Address:</label> <div class="col-md-8"> @Html.TextBox("Address", null, htmlAttributes: new { @class = "form-control", id = "adrs" }) </div> </div> <div class="form-group"> <label for="ct" class="control-label col-md-4 caption">City:</label> <div class="col-md-8"> @Html.TextBox("City", null, htmlAttributes: new { @class = "form-control", id = "ct" }) </div> </div> <div class="form-group"> <label for="county" class="control-label col-md-4 caption">County:</label> <div class="col-md-8"> @Html.TextBox("County", null, htmlAttributes: new { @class = "form-control", id = "county" }) </div> </div> <div class="form-group"> <label for="state" class="control-label col-md-4 caption">State:</label> <div class="col-md-8"> @Html.TextBox("State", null, htmlAttributes: new { @class = "form-control", id = "state" }) </div> </div> <div class="form-group"> <label for="zip" class="control-label col-md-4 caption">ZIP Code:</label> <div class="col-md-8"> @Html.TextBox("ZIPCode", null, htmlAttributes: new { @class = "form-control", id = "zip" }) </div> </div> <div class="form-group"> <label class="control-label col-md-5"> @Html.ActionLink("Customers", "Index", null, htmlAttributes: new { @class = "water-nav" }) </label> <div class="col-md-7"> <input type="submit" value="Create Customer Account" class="btn btn-primary" /> </div> </div> </div> } @Scripts.Render("~/bundles/jquery") <script type="text/javascript"> $(document).ready(function () { $("#mtrNbr").blur(function (event) { var connection = { url: "/WaterDistribution/WaterMeters.xml", method: "GET", dataType: "xml" }; $.ajax(connection). done(function (data) { var waterMeters = $(data).find("water-meter"); waterMeters.each(function () { if ($(this).find("meter-number").text() == $("#mtrNbr").val()) $("#meterDetails").val($(this).find("make").text() + " " + $(this).find("model").text() + " (" + $(this).find("meter-size").text() + ")"); }); }); }); // Lost Focus Event }); // Document.Ready </script>
Accessing a First Child Node
In our videos.xml file, the first child of the first video node is the <title>The Distinguished Gentleman</title> element. The first child of the second <video> node is <title>Her Alibi</title>.
To let you get the first child of a node, the XmlNode class provides a property named FirstChild. It is declared as follows:
public virtual XmlNode FirstChild { get; }
In the following example, every time the parser gets to a video node, it displays the value of it first child:
@{
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();
string strVideosFile = Server.MapPath("~/App_Data/Videos.xml");
if (File.Exists(strVideosFile))
{
xdVideos.Load(strVideosFile);
System.Xml.XmlElement xeVideo = xdVideos.DocumentElement;
System.Xml.XmlNodeList xnlVideos = xeVideo.ChildNodes;
<ul>
@foreach (System.Xml.XmlNode node in xnlVideos)
{
<li>@node.FirstChild.InnerText</li>
}
</ul>
}
}
This would produce:
In this example, we started our parsing on the root node of the document. At times, you will need to consider only a particular node, such as the first child of a node. For example, you may want to use only the first child of the root. To get it, you can access the FirstChild property of the DocumentElement object of the DOM. Once you get that node, you can then do what you judge necessary. In the following example, only the values of the child nodes of the first child of the root are displayed:
@{ System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); // Locate the root node and // get a reference to its first child System.Xml.XmlNode node = xdVideos.DocumentElement.FirstChild; // Create a list of the child nodes of // the first node under the root System.Xml.XmlNodeList xnlVideos = node.ChildNodes; // Visit each node for (int i = 0; i < xnlVideos.Count; i++) { // Look for a node named CastMembers if (xnlVideos[i].Name == "CastMembers") { // Once/if you find it, // 1. Access its first child // 2. Create a list of its child nodes System.Xml.XmlNodeList xnlActors = xnlVideos[i].ChildNodes; // Display the values of the nodes <ul> @for (int j = 0; j < xnlActors.Count; j++) { <li>@xnlActors[j].InnerText</li> } </ul> } } } }
This would produce:
The Content of the First Child Node
Consider the following modification of the Videos.xml file:
<?xml version="1.0" encoding="utf-8" ?>
<Videos>
<Video>
<Title>The Distinguished Gentleman</Title>
<Director>Jonathan Lynn</Director>
<CastMembers>
<Actor>Eddie Murphy</Actor>
<Actor>Lane Smith</Actor>
<Actor>Sheryl Lee Ralph</Actor>
<Actor>Joe Don Baker</Actor>
<Actor>Victoria Rowell</Actor>
</CastMembers>
<Length>112 Minutes</Length>
<Format>DVD</Format>
<Rating>R</Rating>
</Video>
<Video>
<Title>Her Alibi</Title>
<Director>Bruce Beresford</Director>
<Length>94 Mins</Length>
<Format>DVD</Format>
<Rating>PG-13</Rating>
</Video>
<Video>
<Title>Chalte Chalte</Title>
<Director>Aziz Mirza</Director>
<Length>145 Mins</Length>
<Format>DVD</Format>
<Rating>N/R</Rating>
</Video>
</Videos>
Remember that when using a loop (for or foreach) applied to an XmlNodeList collection, each node that you access is a complete XmlNode object and may have children. This means that you can further get the ChildNodes node of any node. Here is an example that primarily scans the nodes but looks for one whose name is CastMembers:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); // Locate the root node and // get a reference to its first child System.Xml.XmlNode node = xdVideos.DocumentElement.FirstChild; // Create a list of the child nodes of // the first node under the root System.Xml.XmlNodeList xnlVideos = node.ChildNodes; // Visit each node for (int i = 0; i < xnlVideos.Count; i++) { // Look for a node named CastMembers if (xnlVideos[i].Name == "CastMembers") { // Once/if you find it, // 1. Access its first child // 2. Create a list of its child nodes System.Xml.XmlNodeList xnlActors = xnlVideos[i].ChildNodes; // Display the values of the nodes <ul> @for (int j = 0; j < xnlActors.Count; j++) { <li>@xnlActors[j].InnerText</li> } </ul> } } } }
This would produce:
We have learned that a node or a group of nodes can be nested inside of another node. When you get to a node, you may know or find out that it has children. You may then want to consider only the first child. Here is an example:
@{
string strVideosFile = Server.MapPath("~/App_Data/Videos.xml");
System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument();
if (File.Exists(strVideosFile))
{
xdVideos.Load(strVideosFile);
// Locate the root node and
// get a reference to its first child
System.Xml.XmlNode node = xdVideos.DocumentElement.FirstChild;
// Create a list of the child nodes of
// the first node under the root
System.Xml.XmlNodeList xnlVideos = node.ChildNodes;
// Visit each node
for (int i = 0; i < xnlVideos.Count; i++)
{
// Look for a node named CastMembers
if (xnlVideos[i].Name == "CastMembers")
{
// Once/if you find it,
// 1. Access its first child
// 2. Create a list of its child nodes
System.Xml.XmlNodeList xnlActors = xnlVideos[i].FirstChild.ChildNodes;
// Display the value of its first child node
<ul>
@for (int j = 0; j < xnlActors.Count; j++)
{
<li>@xnlActors[j].InnerText</li>
}
</ul>
}
}
}
}
This would produce:
The Siblings of a Node
Introduction
The child nodes that are nested in a parent node and share the same level are referred to as siblings.
The Next Sibling
To let you access the sibling of a node, the XmlNode class provides a property named NextSibling. It is declared as follows:
public virtual XmlNode NextSibling { get; }
Consider the following XML document:
<?xml version="1.0" encoding="utf-8"?> <Properties> <Property> <PropertyCode>724-795</PropertyCode> <PropertyType>Apartment</PropertyType> <Bedrooms>1</Bedrooms> <Bathrooms>1</Bathrooms> <MonthlyRent>925</MonthlyRent> <Status>Occupied</Status> </Property> <Property> <PropertyCode>296-283</PropertyCode> <PropertyType>Apartment</PropertyType> <Bedrooms>2</Bedrooms> <Bathrooms>1</Bathrooms> <MonthlyRent>1150.50</MonthlyRent> <Status>Available</Status> </Property> </Properties>
Here are examples of using the NextSibling property:
@{ System.Xml.XmlDocument xdProperties = new System.Xml.XmlDocument(); string strPropertiesFile = Server.MapPath("~/App_Data/Properties.xml"); if (File.Exists(strPropertiesFile)) { xdProperties.Load(strPropertiesFile); System.Xml.XmlElement elmProperty = xdProperties.DocumentElement; System.Xml.XmlNodeList lstProperties = elmProperty.ChildNodes; <table border="1"> <tr> <td><b>Property Code</b></td> <td><b>Property Type</b></td> <td><b>Bedrooms</b></td> <td><b>Bathrooms</b></td> <td><b>Monthly Rent</b></td> <td><b>Sales Status</b></td> </tr> @foreach (System.Xml.XmlNode node in lstProperties) { <tr> <td>@node.FirstChild.InnerText</td> <td>@node.FirstChild.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> </tr> } </table> } }
Practical Learning: Using the Siblings of an XML Node
@{ ViewBag.Title = "Water Meters"; } <div class="push-down"> <h2 class="common-font bold text-center">Water Meters</h2> </div> <hr /> <table class="table table-striped common-font"> <tr> <th class="bold">Meter #</th> <th class="bold">Make</th> <th class="bold">Model</th> <th class="bold">Meter Size</th> <th class="bold">Date Last Update</th> <th class="bold">Counter Value</th> <th>@Html.ActionLink("New Water Meter", "Create", null, htmlAttributes: new { @class = "water-nav" })</th> </tr> @if (ViewBag.waterMeters != null) { foreach (System.Xml.XmlNode node in ViewBag.waterMeters as System.Xml.XmlNodeList) { <tr> <td class="text-center">@node.FirstChild.InnerText</td> <td>@node.FirstChild.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td> @Html.ActionLink("Update", "Edit", new { id = @node.FirstChild.InnerText }) | @Html.ActionLink("Review", "Details", new { id = @node.FirstChild.InnerText }) | @Html.ActionLink("Remove", "Delete", new { id = @node.FirstChild.InnerText }) </td> </tr> } } </table>
@{ ViewBag.Title = "Customers Accounts"; } <div class="push-down"> <h2 class="common-font bold text-center">Customers Accounts</h2> </div> <hr /> <table class="table table-striped common-font"> <tr> <th class="bold">Account #</th> <th class="bold">Meter #</th> <th class="bold">First Name</th> <th class="bold">Last Name</th> <th class="bold">Address</th> <th class="bold">City</th> <th class="bold">County</th> <th class="bold">State</th> <th class="bold">ZIP Code</th> <th>@Html.ActionLink("New Customer Account", "Create", null, htmlAttributes: new { @class = "water-nav" })</th> </tr> @if (ViewBag.customers != null) { foreach (System.Xml.XmlNode node in ViewBag.customers as System.Xml.XmlNodeList) { <tr> <td>@node.FirstChild.InnerText</td> <td>@node.FirstChild.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td>@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td> @Html.ActionLink("Update", "Edit", new { id = @node.FirstChild.InnerText }) | @Html.ActionLink("Review", "Details", new { id = @node.FirstChild.InnerText }) | @Html.ActionLink("Remove", "Delete", new { id = @node.FirstChild.InnerText }) </td> </tr> } } </table>
<div class="jumbotron"> <h2>.</h2> <p class="lead"> Our water utility company provides energy, greatness, and warmth for a everyday life, a shining life. We provide solutions to families, businesses, and the community. </p> <p class="lead"> This is the employees portal section of the company. From here, employees can register a new water meter, manage a customer account, or create a water bill. </p> </div> <div class="row"> <div class="col-md-3"> <h2>Water Meters</h2> <p> Our company uses the most accurate, sophisticated, and environment-friendly water meters on the market. </p> <p>@Html.ActionLink("Water Meters", "Index", "WaterMeters", null, new { @class = "btn btn-primary" })</p> </div> <div class="col-md-3"> <h2>Customers</h2> <p> We supply water to individuals, families, small businesses, as well as enterprises or government agencies. </p> <p>@Html.ActionLink("Customers", "Index", "Customers", null, new { @class = "btn btn-primary" })</p> </div> <div class="col-md-3"> <h2>Water Bills</h2> <p> Our water rates are very competitive nationwide. We use precise, effective, and strict algorithms when calculating our bills. </p> <p>@Html.ActionLink("Bills/Invoices", "Index", "WaterBills", null, new { @class = "btn btn-primary" })</p> </div> <div class="col-md-3"> <h2>Payments</h2> <p> Our payment system is the simplest, the fairest, and the fastest. Our custiomer's service is highly rated. </p> <p>@Html.ActionLink("Bills Payments", "Index", "Payments", null, new { @class = "btn btn-primary" })</p> </div> </div>
Meter # | Make | Model | Meter Size | Date Last Update | Counter Value |
392-44-572 | Constance Technologies | TG-4822 | 5/8 Inches | 03/31/2018 | 109992 |
938-75-869 | Standard Trend | 266G | 1 1/2 Inches | 10/22/2017 | 137926 |
799-28-461 | Constance Technologies | BD-7000 | 3/4 Inches | 05/05/2018 | 6268 |
207-94-835 | Constance Technologies | TG-6220 | 5/8 Inches | 02/17/2018 | 96 |
592-84-957 | Standard Trend | 428T | 3/4 Inches | 12/07/2018 | 49 |
Account # | Meter # | First Name | Last Name | Address | City | County | State | ZIP Code |
9279-570-8394 | 799-28-461 | Thomas | Stones | 10252 Broward Ave #D4 | Frederick | Frederick | MD | 21703 |
4820-375-2842 | 392-44-572 | Akhil | Koumari | 748 Red Hills Rd | Roanoke | VA | 24012 | |
7518-302-6895 | 207-94-835 | Grace | Brenner | 4299 Peachtree Court | Rockville | Montgomery | MD | 20853 |
2038-413-9680 | 938-75-869 | Amidou | Gomah | 2075 Rose Hills Ave | Washington | DC | 20004 | |
5938-074-5293 | 592-84-957 | Marie | Rath | 582G Dunhill Ave | Lanham | Prince Georges | MD | 20706 |
using System; using System.Collections.Generic; using System.IO; using System.Xml; using System.Web.Mvc; namespace WaterDistribution2.Controllers { public class WaterBillsController : Controller { // GET: WaterBills public ActionResult Index() { return View(); } // GET: WaterBills/WaterBillStartUp public ActionResult WaterBillStartUp() { return View(); } // GET: WaterBills/BillPreparation public ActionResult BillPreparation(string AccountNumber, string MeterReadingStartDate, string MeterReadingEndDate, string CounterReadingStart, string CounterReadingEnd) { /* We will start our invoices numbers at 1000001. * For now, assuming that there is no bill yet, let's set the starting number at 100000. */ int invoiceNumber = 100000; XmlDocument xdCustomers = new XmlDocument(); XmlDocument xdWaterBills = new XmlDocument(); XmlDocument xdWaterMeters = new XmlDocument(); string strFileCustomers = Server.MapPath("/WaterDistribution/Customers.xml"); string strFileWaterBills = Server.MapPath("/WaterDistribution/WaterBills.xml"); string strFileWaterMeters = Server.MapPath("/WaterDistribution/WaterMeters.xml"); // Make sure the user provided all the minimum pieces of information that were requested. if (!string.IsNullOrEmpty(AccountNumber) && !string.IsNullOrEmpty(MeterReadingStartDate) && !string.IsNullOrEmpty(MeterReadingEndDate) && !string.IsNullOrEmpty(CounterReadingStart) && !string.IsNullOrEmpty(CounterReadingEnd)) { // We need to create an invoice number // To start, find out if a file for water bills exists already. if (System.IO.File.Exists(strFileWaterBills)) { // If a file for water bills exists, open that file using (FileStream fsWaterBills = new FileStream(strFileWaterBills, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Get the list of water bills from the file and put that list in the XML document xdWaterBills.Load(fsWaterBills); /* Since it appears that we currently have a list of bills, get each bill's markup. */ XmlNodeList xnlWaterBills = xdWaterBills.DocumentElement.ChildNodes; // Visit each invoice/bill foreach (XmlNode xnWaterBill in xnlWaterBills) { // When you get to a list of nodes, create a list of its children and visit each foreach (XmlNode xnInvoice in xnWaterBill.ChildNodes) { if (xnInvoice.Name == "invoice-number") { invoiceNumber = int.Parse(xnInvoice.InnerText); } } } } } if (System.IO.File.Exists(strFileCustomers)) { // ... open that file using (FileStream fsCustomers = new FileStream(strFileCustomers, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Get the list of customers from the file and put that list in our initial empty list of customers xdCustomers.Load(fsCustomers); /* Since it appears that we currently have a list of customers, let's find out if * it contains a customer with the account number that was entered in the form. */ XmlNodeList xnlCustomers = xdCustomers.DocumentElement.ChildNodes; // Visit each node of the list of elements foreach (XmlNode xnCustomer in xnlCustomers) { // When you get to a list of nodes, create a list of its children and visit each foreach (XmlNode xnInvoice in xnCustomer.ChildNodes) { // If you find a meter number that is the same as the meter number from the form, ... if (xnInvoice.InnerText == Request["AccountNumber"]) { /* Now that we have a customer with that account number, * let's prepare to send the account information to the view. */ ViewBag.MeterNumber = xnInvoice.NextSibling.InnerText; ViewBag.FirstName = xnInvoice.NextSibling.NextSibling.InnerText; ViewBag.LastName = xnInvoice.NextSibling.NextSibling.NextSibling.InnerText; ViewBag.Address = xnInvoice.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; ViewBag.City = xnInvoice.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; ViewBag.County = xnInvoice.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; ViewBag.State = xnInvoice.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; ViewBag.ZIPCode = xnInvoice.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; } } } } // Using } else { ViewBag.ErrorMessage = "There is no customer with that account number."; } if (System.IO.File.Exists(strFileWaterMeters)) { // ... open that file using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.Open, FileAccess.Read, FileShare.Read)) { // Get the list of customers from the file and put that list in our initial empty list of customers xdWaterMeters.Load(fsWaterMeters); /* Since it appears that we currently have a list of customers, let's find out if * it contains a customer with the account number that was entered in the form. */ XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement.ChildNodes; // Visit each node of the list of elements foreach (XmlNode xnWaterMeter in xnlWaterMeters) { // When you get to a list of nodes, create a list of its children and visit each foreach (XmlNode xnMeterNumber in xnWaterMeter.ChildNodes) { // If you find a meter number that is the same as the meter number from the form, ... if (xnMeterNumber.InnerText == ViewBag.MeterNumber) { ViewBag.MeterDetails = xnMeterNumber.NextSibling.InnerText + " " + xnMeterNumber.NextSibling.NextSibling.InnerText + ", " + xnMeterNumber.NextSibling.NextSibling.NextSibling.InnerText; } } } } // Using } else { ViewBag.ErrorMessage = "There is no water meter with that number."; } /* Whether there was a list of invoice numbers already or not, * increase the current invoice number by 1. * And send the number to the view. */ ViewBag.InvoiceNumber = invoiceNumber + 1; /* Let's compute the numbers for the water bill. * The following calculations are not based on anything real. * I used my own rough estimates with weird non-extensive research based on nothing. * These calculations are for demonstration purposes only for our lesson. */ float next10HCF = 0.00f; float first15HCF = 0.00f; float remainingHCF = 0.00f; TimeSpan tsDays = new TimeSpan(); DateTime dtMeterReadingEndDate = DateTime.Parse(MeterReadingEndDate); DateTime dtMeterReadingStartDate = DateTime.Parse(MeterReadingStartDate); float fCounterReadingStart = float.Parse(CounterReadingStart); float fCounterReadingEnd = float.Parse(CounterReadingEnd); tsDays = dtMeterReadingEndDate - dtMeterReadingStartDate; float totalHCF = fCounterReadingEnd - fCounterReadingStart; int totalGallons = (int)(totalHCF * 748.05); if (totalHCF <= 15) { first15HCF = totalHCF * 3.612f; next10HCF = 0f; remainingHCF = 0f; } else if (totalHCF <= 25f) { first15HCF = 15f * 3.612f; next10HCF = (totalHCF - 15f) * 3.918f; remainingHCF = 0f; } else { first15HCF = 15f * 3.612f; next10HCF = 10f * 3.918f; remainingHCF = (totalHCF - 25f) * 2.2763f; } double waterUsageCharge = first15HCF + next10HCF + remainingHCF; double sewerCharge = waterUsageCharge * 0.252; double stormCharge = waterUsageCharge * 0.0025; double totalCharges = waterUsageCharge + sewerCharge + stormCharge; double countyTaxes = totalCharges * 0.005; double stateTaxes = totalCharges * 0.0152; double amountDue = totalCharges + countyTaxes + stateTaxes; ViewBag.TotalHCF = totalHCF; ViewBag.Next10HCF = next10HCF; ViewBag.AmountDue = amountDue; ViewBag.StateTaxes = stateTaxes; ViewBag.First15HCF = first15HCF; ViewBag.SewerCharge = sewerCharge; ViewBag.StormCharge = stormCharge; ViewBag.CountyTaxes = countyTaxes; ViewBag.BillingDays = tsDays.Days; ViewBag.TotalGallons = totalGallons; ViewBag.RemainingHCF = remainingHCF; ViewBag.TotalCharges = totalCharges; ViewBag.LateAmountDue = amountDue + 8.95; ViewBag.WaterUsageCharge = waterUsageCharge; ViewBag.PaymentDueDate = dtMeterReadingEndDate.AddDays(28); ViewBag.LatePaymentDueDate = dtMeterReadingEndDate.AddDays(45); } return View(); } // POST: WaterBills/SaveWaterBill public ActionResult SaveWaterBill(string InvoiceNumber, string MeterReadingStartDate, string MeterReadingEndDate, string BillingDays, string CounterReadingStart, string CounterReadingEnd, string TotalHCF, string TotalGallons, string First15HCF, string Next10HCF, string RemainingHCF, string SewerCharges, string StormCharges, string WaterUsageCharges, string TotalCharges, string CountyTaxes, string StateTaxes, string PaymentDueDate, string AmountDue, string LatePaymentDueDate, string LateAmountDue) { XmlDocument xdWaterBills = new XmlDocument(); string strFileWaterBills = Server.MapPath("/WaterDistribution/WaterBills.xml"); if (!string.IsNullOrEmpty(InvoiceNumber)) { if (System.IO.File.Exists(strFileWaterBills)) { using (FileStream fsWaterBills = new FileStream(strFileWaterBills, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { // ... and put the records in the DOM xdWaterBills.Load(fsWaterBills); } } else { xdWaterBills.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + "<water-bills></water-bills>"); } XmlElement xeWaterBill = xdWaterBills.CreateElement("water-bill"); xeWaterBill.InnerXml = "<invoice-number>" + InvoiceNumber + "</invoice-number>" + "<meter-reading-start-date>" + MeterReadingStartDate + "</meter-reading-start-date>" + "<meter-reading-end-date>" + MeterReadingEndDate + "</meter-reading-end-date>" + "<billing-days>" + BillingDays + "</billing-days>" + "<counter-reading-start>" + CounterReadingStart + "</counter-reading-start>" + "<counter-reading-end>" + CounterReadingEnd + "</counter-reading-end>" + "<total-hcf>" + TotalHCF + "</total-hcf>" + "<total-gallons>" + TotalGallons + "</total-gallons>" + "<first15-hcf>" + First15HCF + "</first15-hcf>" + "<next10-hcf>" + Next10HCF + "</next10-hcf>" + "<remaining-hcf>" + RemainingHCF + "</remaining-hcf>" + "<sewer-charges>" + SewerCharges + "</sewer-charges>" + "<storm-charges>" + StormCharges + "</storm-charges>" + "<water-usage-charges>" + WaterUsageCharges + "</water-usage-charges>" + "<total-charges>" + TotalCharges + "</total-charges>" + "<county-taxes>" + CountyTaxes + "</county-taxes>" + "<state-taxes>" + StateTaxes + "</state-taxes>" + "<payment-due-date>" + PaymentDueDate + "</payment-due-date>" + "<amount-due>" + AmountDue + "</amount-due>" + "<late-payment-due-date>" + LatePaymentDueDate + "</late-payment-due-date>" + "<late-amount-due>" + LateAmountDue + "</late-amount-due>"; xdWaterBills.DocumentElement.AppendChild(xeWaterBill); // Save the (new version of the) XML file using (FileStream fsWaterBills = new FileStream(strFileWaterBills, FileMode.Create, FileAccess.Write, FileShare.Write)) { xdWaterBills.Save(fsWaterBills); } } return RedirectToAction("WaterBillStartUp"); } } }
@{ ViewBag.Title = "Water Bill Start-Up"; } <div class="push-down"> <h2 class="text-center">Water Bill Start-Up</h2> </div> <hr /> <div align="center"> @using (Html.BeginForm("BillPreparation", "WaterBills", FormMethod.Post)) { <table> <tr> <td class="ctl-deco">Account #:</td> <td>@Html.TextBox("AccountNumber", "", new { @class = "form-control medium" })</td> <td class="large-col"> </td> <td> </td> </tr> <tr> <td class="ctl-deco">Service Start Date:</td> <td>@Html.TextBox("MeterReadingStartDate", "", new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Service to:</td> <td>@Html.TextBox("MeterReadingEndDate", "", new { @class = "form-control medium" })</td> </tr> <tr> <td class="ctl-deco">Counter Reading Start:</td> <td>@Html.TextBox("CounterReadingStart", "", new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Counter Reading End:</td> <td>@Html.TextBox("CounterReadingEnd", "", new { @class = "form-control medium" })</td> </tr> </table> <hr /> <p class="text-center"><input type="submit" name="btnCreateWaterBill" value="Create Water Bill" class="btn btn-primary medium" /></p> } <table> <tr> <td style="width: 120px"> </td> <td>@Html.ActionLink("New Water Meter", "Create", "WaterMeters", new { @class = "navbar-brand" }) @Html.ActionLink("Create Customer Account", "Create", "Customers", new { @class = "navbar-brand" }) </td> </tr> </table> </div>
@{ ViewBag.Title = "Bill Preparation"; } <div class="push-down"> <h2 class="text-center">Bill Preparation</h2> </div> @{ string strCity = ViewBag.City; string strState = ViewBag.State; string strCounty = ViewBag.County; string strAddress = ViewBag.Address; string strZIPCode = ViewBag.ZIPCode; string strLastName = ViewBag.LastName; string strFirstName = ViewBag.FirstName; string meterNumber = ViewBag.MeterNumber; string meterDetails = ViewBag.MeterDetails; int days = ViewBag.BillingDays; float totalHCF = ViewBag.TotalHCF; float next10HCF = ViewBag.Next10HCF; double amountDue = ViewBag.AmountDue; double stateTaxes = ViewBag.StateTaxes; double first15HCF = ViewBag.First15HCF; int totalGallons = ViewBag.TotalGallons; double countyTaxes = ViewBag.CountyTaxes; double sewerCharges = ViewBag.SewerCharge; double stormCharges = ViewBag.StormCharge; float remainingHCF = ViewBag.RemainingHCF; int invoiceNumber = ViewBag.InvoiceNumber; double totalCharges = ViewBag.TotalCharges; double lateAmountDue = ViewBag.LateAmountDue; DateTime paymentDueDate = ViewBag.PaymentDueDate; double waterUsageCharges = ViewBag.WaterUsageCharge; DateTime latePaymentDueDate = ViewBag.LatePaymentDueDate; } @using (Html.BeginForm("SaveWaterBill", "WaterBills", FormMethod.Post)) { <div class="highligh">Customer Account Information</div> <br /> <table style="width: 460px"> <tr> <td class="ctl-deco medium">Account #:</td> <td>@Html.TextBox("AccountNumber", "AccountNumber", new { @class = "form-control medium" })</td> <td> </td> </tr> <tr> <td class="ctl-deco">Customer Name:</td> <td>@Html.TextBox("FirstName", @strFirstName, new { @class = "form-control medium" })</td> <td class="text-left">@Html.TextBox("LastName", @strLastName, new { @class = "form-control medium" })</td> </tr> </table> <table class="bill-contents"> <tr> <td class="ctl-deco medium">Address:</td> <td colspan="4">@Html.TextBox("Address", @strAddress, new { @class = "form-control" })</td> </tr> <tr> <td> </td> <td>@Html.TextBox("City", @strCity, new { @class = "form-control medium" })</td> <td>@Html.TextBox("County", @strCounty, new { @class = "form-control medium" })</td> <td>@Html.TextBox("State", @strState, new { @class = "form-control small" })</td> <td>@Html.TextBox("ZIPCode", @strZIPCode, new { @class = "form-control small" })</td> </tr> </table> <br /> <div class="highligh">Meter Information</div> <br /> <table style="width: 600px"> <tr> <td class="ctl-deco medium">Meter Details:</td> <td>@Html.TextBox("MeterNumber", @meterNumber, new { @class = "form-control medium" })</td> <td>@Html.TextBox("MeterDetails", @meterDetails, new { @class = "form-control xlarge" })</td> </tr> </table> <table> <tr> <td class="ctl-deco medium">Service Start Date:</td> <td>@Html.TextBox("MeterReadingStartDate", "MeterReadingStartDate", new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Service to:</td> <td>@Html.TextBox("MeterReadingEndDate", "MeterReadingEndDate", new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Number of Days:</td> <td>@Html.TextBox("BillingDays", @days, new { @class = "form-control medium" })</td> </tr> <tr> <td class="ctl-deco">Counter Reading Start:</td> <td>@Html.TextBox("CounterReadingStart", @"CounterReadingStart", new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Counter Reading End:</td> <td>@Html.TextBox("CounterReadingEnd", @"CounterReadingEnd", new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Total HCF:</td> <td>@Html.TextBox("TotalHCF", @totalHCF.ToString("F"), new { @class = "form-control medium" })</td> </tr> <tr> <td> </td> <td> </td> <td> </td> <td> </td> <td class="ctl-deco text-right">Total Gallons:</td> <td>@Html.TextBox("TotalGallons", @totalGallons, new { @class = "form-control medium" })</td> </tr> <tr> <td class="ctl-deco">1st 15 HCF at $3.6121:</td> <td>@Html.TextBox("First15HCF", @first15HCF.ToString("F"), new { @class = "form-control medium" })</td> <td class="ctl-deco">Next 10 HCF at $3.9180:</td> <td class="text-right">@Html.TextBox("Next10HCF", @next10HCF.ToString("F"), new { @class = "form-control medium" })</td> <td class="ctl-deco">Remaining HCF at $4.2763:</td> <td>@Html.TextBox("RemainingHCF", @remainingHCF.ToString("F"), new { @class = "form-control medium" })</td> </tr> <tr> <td class="ctl-deco">Sewer Charges:</td> <td>@Html.TextBox("SewerCharges", @sewerCharges.ToString("F"), new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Storm Charges:</td> <td class="text-right">@Html.TextBox("StormCharges", @stormCharges.ToString("F"), new { @class = "form-control medium" })</td> <td class="ctl-deco text-right">Water Usage Charges:</td> <td>@Html.TextBox("WaterUsageCharges", @waterUsageCharges.ToString("F"), new { @class = "form-control medium" })</td> </tr> <tr> <td></td> <td> </td> <td> </td> <td> </td> <td class="ctl-deco text-right">Total Charges:</td> <td>@Html.TextBox("TotalCharges", @totalCharges.ToString("F"), new { @class = "form-control medium" })</td> </tr> </table> <br /> <div class="highligh">Water Bill Values</div> <br /> <table> <tr> <td class="xlarge-col text-right">County Taxes:</td> <td>@Html.TextBox("CountyTaxes", @countyTaxes.ToString("F"), new { @class = "form-control medium" })</td> <td class="large-col text-right">State Taxes:</td> <td>@Html.TextBox("StateTaxes", @stateTaxes.ToString("F"), new { @class = "form-control medium" })</td> </tr> </table> <hr /> <table> <tr> <td class="xlarge-col text-right">Payment Due Date:</td> <td>@Html.TextBox("PaymentDueDate", @paymentDueDate.ToShortDateString(), new { @class = "form-control medium" })</td> <td class="large-col text-right">Amount Due:</td> <td>@Html.TextBox("AmountDue", @amountDue.ToString("F"), new { @class = "form-control medium" })</td> </tr> <tr> <td class="xlarge-col text-right">Late Payment Due Date:</td> <td>@Html.TextBox("LatePaymentDueDate", @latePaymentDueDate.ToShortDateString(), new { @class = "form-control medium" })</td> <td class="large-col text-right ">Late Payment Amount:</td> <td>@Html.TextBox("LateAmountDue", @lateAmountDue.ToString("F"), new { @class = "form-control medium" })</td> </tr> </table> <hr /> <table> <tr> <td class="xlarge-col text-right">Invoice #:</td> <td>@Html.TextBox("InvoiceNumber", @invoiceNumber, new { @class = "form-control medium" })</td> <td class="large-col"> </td> <td class="text-right"><input type="submit" name="btnSaveWaterBill" value="Save Water Bill" class="btn btn-primary large" /></td> </tr> </table> }
@{ ViewBag.Title = "Water Distribution Company - Customers"; } <div class="push-down"> <h2 class="text-center">Water Distribution Company - Customers</h2> @{ System.Xml.XmlNodeList xnlCustomers = ViewBag.customers; <table style="border: 3px solid #ffd800; color: aquamarine; width: 800px; margin: auto;"> <tr> <td class="bold tbl-head">Account #</td> <td class="bold tbl-head">Meter #</td> <td class="bold tbl-head">FirstName</td> <td class="bold tbl-head">LastName</td> <td class="bold tbl-head">Address</td> <td class="bold tbl-head">City</td> <td class="bold tbl-head">County</td> <td class="bold tbl-head">State</td> <td class="bold tbl-head">ZIP Code</td> </tr> @foreach (System.Xml.XmlNode node in xnlCustomers) { <tr> <td class="tbl-cell">@node.FirstChild.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> <td class="tbl-cell">@node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText</td> </tr> } </table> } <p class="text-center">@Html.ActionLink("New Customer Account", "Create", "Customers", null, new { @class = "navbar-brand" }) :: @Html.ActionLink("Customer Account Review", "Details", "Customers", null, new { @class = "navbar-brand" }) </p> </div>
@{ ViewBag.Title = "Water Distribution Company - Customer Details"; } <div class="push-down"> <h2 class="text-center">Water Distribution Company - Customer Details</h2> </div> @{ string zip = string.Empty; string adrs = string.Empty; string city = string.Empty; string state = string.Empty; string county = string.Empty; string lastName = string.Empty; string firstName = string.Empty; string mtrNumber = string.Empty; string acntNumber = string.Empty; string mtrDetails = string.Empty; System.Xml.XmlDocument xdWaterMeters = new System.Xml.XmlDocument(); System.Xml.XmlDocument xdCustomers = new System.Xml.XmlDocument(); string strFileCustomers = Server.MapPath("/WaterDistribution/Customers.xml"); string strFileWaterMeters = Server.MapPath("/WaterDistribution/WaterMeters.xml"); if (IsPost) { acntNumber = Request["AccountNumber"]; // If an XML file for customers accounts was previously created, ... if (System.IO.File.Exists(strFileCustomers)) { // ... open it ... using (FileStream fsCustomers = new FileStream(strFileCustomers, FileMode.Open, FileAccess.Read, FileShare.Read)) { // ... and put the records in the DOM xdCustomers.Load(fsCustomers); } } System.Xml.XmlNodeList xnlCustomers = xdCustomers.DocumentElement.ChildNodes; foreach (System.Xml.XmlNode xnCustomer in xnlCustomers) { if (xnCustomer.FirstChild.InnerText == acntNumber) { mtrNumber = xnCustomer.FirstChild.NextSibling.InnerText; firstName = xnCustomer.FirstChild.NextSibling.NextSibling.InnerText; lastName = xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.InnerText; adrs = xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; city = xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; county = xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; state = xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; zip = xnCustomer.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText; } } if (System.IO.File.Exists(strFileWaterMeters)) { using (FileStream fsWaterMeters = new FileStream(strFileWaterMeters, FileMode.Open, FileAccess.Read, FileShare.Read)) { xdWaterMeters.Load(fsWaterMeters); } } System.Xml.XmlNodeList xnlWaterMeters = xdWaterMeters.DocumentElement.ChildNodes; foreach (System.Xml.XmlNode xnWaterMeter in xnlWaterMeters) { if (xnWaterMeter.FirstChild.InnerText == mtrNumber) { mtrDetails = xnWaterMeter.FirstChild.NextSibling.InnerText + " " + xnWaterMeter.FirstChild.NextSibling.NextSibling.InnerText + " (" + xnWaterMeter.FirstChild.NextSibling.NextSibling.NextSibling.InnerText + ")"; } } } } <div align="center"> @using (Html.BeginForm()) { <table style="width: 550px"> <tr> <td class="small ctl-deco">Account #:</td> <td>@Html.TextBox("AccountNumber", @acntNumber, new { @class = "form-control medium" })</td> <td class="text-left"><input type="submit" name="btnFind" value="Find Customer" class="btn btn-primary medium" /></td> </tr> </table> <table style="width: 550px"> <tr> <td class="small ctl-deco">Meter #:</td> <td>@Html.TextBox("MeterNumber", @mtrNumber, htmlAttributes: new { @class = "form-control medium" })</td> <td>@Html.TextBox("MeterDetails", @mtrDetails, htmlAttributes: new { @class = "form-control xlarge" })</td> </tr> </table> <table style="width: 550px"> <tr> <td class="small ctl-deco">First Name:</td> <td>@Html.TextBox("FirstName", @firstName, new { @class = "form-control medium" })</td> <td class="small ctl-deco"> Last Name:</td> <td>@Html.TextBox("LastName", @lastName, new { @class = "form-control medium" })</td> </tr> <tr> <td class="ctl-deco">Address:</td> <td colspan="3">@Html.TextBox("Address", @adrs, new { @class = "form-control xxlarge" })</td> </tr> <tr> <td class="ctl-deco">City:</td> <td>@Html.TextBox("City", @city, new { @class = "form-control medium" })</td> <td class="ctl-deco"> County:</td> <td>@Html.TextBox("County", @county, new { @class = "form-control medium" })</td> </tr> <tr> <td class="ctl-deco">State:</td> <td>@Html.TextBox("State", @state, new { @class = "form-control medium" })</td> <td class="ctl-deco"> ZIP-Code:</td> <td>@Html.TextBox("ZIPCode", @zip, new { @class = "form-control medium" })</td> </tr> </table> <hr /> <table> <tr> <td>@Html.ActionLink("New Customer Account", "Create", "Customers", null, new { @class = "navbar-brand" })</td> <td class="text-center">@Html.ActionLink("Customers Records", "Index", "Customers", null, new { @class = "navbar-brand" })</td> </tr> </table> } </div>
@{ ViewBag.Title = "Welcome"; } <div class="jumbotron"> <h2>.</h2> <p class="lead"> Our water utility company provides energy, greatness, and warmth for a everyday life, a shining life. We provide solutions to families, businesses, and the community. </p> <p class="lead"> This is the employees portal section of the company. From here, employees can register a new water meter, manage a customer account, or create a water bill. </p> </div> <div class="row"> <div class="col-md-4"> <h2>Water Meters</h2> <p> Our company uses the most accurate, sophisticated, and environment-friendly water meters on the market. Our suppliers care. </p> <p>@Html.ActionLink("Create Water Meter", "Create", "WaterMeters", null, new { @class = "btn btn-primary" })</p> </div> <div class="col-md-4"> <h2>Customers</h2> <p> We supply water to individuals, families, small businesses, as well as enterprises or government agencies. </p> <p>@Html.ActionLink("Create Customer Account", "Create", "Customers", null, new { @class = "btn btn-primary" })</p> </div> <div class="col-md-4"> <h2>Water Bills</h2> <p> Our water rates are very competitive nationwide. We use precise, effective, and strict algorithms when performing our water bills calculations. </p> <p>@Html.ActionLink("Create Water Bill", "WaterBillStartUp", "WaterBills", null, new { @class = "btn btn-primary" })</p> </div> </div>
Meter # | Make | Model | Meter Size |
293-740 | Breston | S-93749 | 3/4 Inches |
820-418 | Vashty Worldwide | DD-3840 | 3/4 Inches |
627-425 | Breston | T-39478 | 5/8 Inches |
304-861 | Vashty Worldwide | DD-3840 | 3/4 Inches |
925-935 | Igawa International | DTT 8802 | 1 Inch |
779-958 | Igawa International | DMG 4000 | 3/4 Inches |
<?xml version="1.0" encoding="utf-8"?> <water-meters> <water-meter> <meter-number>293-740</meter-number> <make>Breston</make> <model>S-93749</model> <meter-size>3/4 Inches</meter-size> </water-meter> <water-meter> <meter-number>820-418</meter-number> <make>Vashty Worldwide</make> <model>DD-3840</model> <meter-size>3/4 Inches</meter-size> </water-meter> <water-meter> <meter-number>627-425</meter-number> <make>Breston</make> <model>T-39478</model> <meter-size>5/8 Inches</meter-size> </water-meter> <water-meter> <meter-number>304-861</meter-number> <make>Vashty Worldwide</make> <model>DD-3840</model> <meter-size>3/4 Inches</meter-size> </water-meter> <water-meter> <meter-number>925-935</meter-number> <make>Igawa International</make> <model>DTT 8802</model> <meter-size>1 Inch</meter-size> </water-meter> <water-meter> <meter-number>779-958</meter-number> <make>Igawa International</make> <model>DMG 4000</model> <meter-size>3/4 Inches</meter-size> </water-meter> </water-meters>
Account # | Meter # | First Name | Last Name | Address | City | County | State | ZIP Code |
2958-314-5294 | 627-425 | Nicholas | Thorn | 2599 Phenicia Road | Silver Spring | Montgomery | MD | 20906 |
8046-728-5060 | 304-861 | Augustino | Derbez | 7507 Westchester Ave | Washington | DC | 20008 | |
4024-850-0482 | 820-418 | Marianne | Pattersen | 10572 Maya Blvd | Frederick | Frederick | MD | 20111 |
1848-205-3313 | 925-935 | Frank | Nounkeu | 13931 Wellington Street | College Park | Pringe George | MD | 20740 |
7029-371-8594 | 293-740 | Danielle | Dormand | 2515 Guthierez Street | Falls Church | VA | 22046 |
<?xml version="1.0" encoding="utf-8"?> <customers> <customer> <account-number>7029-371-8594</account-number> <meter-number>293-740</meter-number> <first-name>Danielle</first-name> <last-name>Dormand</last-name> <address>2515 Guthierez Street</address> <city>Falls Church</city> <county> </county> <state>VA</state> <zip-code>22046</zip-code> </customer> <customer> <account-number>1848-205-3313</account-number> <meter-number>925-935</meter-number> <first-name>Frank</first-name> <last-name>Nounkeu</last-name> <address>13931 Wellington Street</address> <city>College Park</city> <county>Prince George</county> <state>MD</state> <zip-code>20740</zip-code> </customer> <customer> <account-number>4024-850-0482</account-number> <meter-number>820-418</meter-number> <first-name>Marianne</first-name> <last-name>Pettersen</last-name> <address>10572 Maya Blvd</address> <city>Frederick</city> <county>Frederick</county> <state>MD</state> <zip-code>20111</zip-code> </customer> <customer> <account-number>8046-728-5060</account-number> <meter-number>304-861</meter-number> <first-name>Augustino</first-name> <last-name>Derbez</last-name> <address>7507 Westchester Ave</address> <city>Washington</city> <county> </county> <state>DC</state> <zip-code>20008</zip-code> </customer> <customer> <account-number>2958-314-5294</account-number> <meter-number>627-425</meter-number> <first-name>Nicholas</first-name> <last-name>Thorn</last-name> <address>2599 Phenicia Road</address> <city>Silver Spring</city> <county>Montgomery</county> <state>MD</state> <zip-code>20906</zip-code> </customer> </customers>
Account # | 1848-205-3313 |
Service Start Date | 1/12/2018 |
Service To | 4/17/2018 |
Meter Reading Start | 274.68 |
Reading End | 316.53 |
Account # | 2958-314-5294 |
Service Start Date | 1/18/2018 |
Service To | 4/17/2018 |
Meter Reading Start | 5827.59 |
Reading End | 5883.17 |
Account # | 4024-850-0482 |
Service Start Date | 4/14/2018 |
Service To | 7/6/2018 |
Meter Reading Start | 1436.64 |
Reading End | 1454.86 |
Inserting an Element Before 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:
@{ string strVideosFile = Server.MapPath("~/App_Data/Videos.xml"); System.Xml.XmlDocument xdVideos = new System.Xml.XmlDocument(); if (File.Exists(strVideosFile)) { xdVideos.Load(strVideosFile); // Get a reference to the root node System.Xml.XmlElement xeRoot = xdVideos.DocumentElement; // Create a list of the videos System.Xml.XmlNodeList xnlVideos = xdVideos.GetElementsByTagName("video"); // visit each video foreach (System.Xml.XmlNode node in xnlVideos) { // Within a video, create a list of its children System.Xml.XmlNodeList lstChildren = node.ChildNodes; // Visit each child node foreach (System.Xml.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 System.Xml.XmlElement xeNewVideo = xdVideos.CreateElement("category"); // Specify the text of the new element xeNewVideo.InnerText = "Drama"; // Insert the new node below the Adrian Lyne node Director node.InsertAfter(xeNewVideo, dir); // Save the file xdVideos.Save(strVideosFile); // Stop looking for the child 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>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.
To let you position a new node after an existing child node, the XmlNode class provides a method named InsertAfter. Its syntax is:
public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild);
Practical Learning: Ending the Lesson
|
||
Previous | Copyright © 2005-2018, FunctionX | Next |
|