Operations on XML Elements |
|
Creating an XML Element
Introduction
To create an XML element, you can directly type the XML code in a document and then save the file with and .xml extension. As an alternative and as we saw in our introduction, you can call the XmlDocument.LoadXml() method to which you would pass the starting XML code, then save the file by calling the XmlDocument.Save() method to which you would pass the name (and/or path) of the file. This can be done as follows:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click
Dim xdHouseTypes As New XmlDocument()
Dim strHouseTypesFile = Server.MapPath("exercises/HouseTypes.xml")
xdHouseTypes.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" &
"<house-types>" &
" <category>Condominium</category>" &
"</house-types>")
xdHouseTypes.Save(strHouseTypesFile)
End Sub
</script>
<title>Altair Realtors - House Type</title>
</head>
<body>
<h3>Altair Realtors - House Type</h3>
<form id="frmRoads" runat="server">
<asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?> <house-types> <category>Condominium</category> </house-types>
In some cases, 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 add a new element.
Creating an Element
To assist you with programmatically creating a new element, the XmlDocument class is equipped with a method named CreateElement that is overloaded with three versions. One of the versions uses the following syntax:
Public Function CreateElement(ByVal name As String) As XmlElement
To create a new element, call this method and pass it the name of the element. Here is an example:
<%@ Page Language="VB" %> <%@ Import Namespace="System.Xml" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click Dim xeHouseType As XmlElement Dim xdHouseTypes As New XmlDocument() Dim strHouseTypesFile = Server.MapPath("exercises/HouseTypes.xml") xdHouseTypes.Load(strRoadsFile) xeHouseType = xdHouseTypes.CreateElement("category") End Sub </script> <title>Altair Realtors - House Type</title> </head> <body> <h3>Altair Realtors - House Type</h3> <form id="frmHouseTypes" runat="server"> <asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button> </form> </body> </html>
Appending an Element
In order to add the new element to the document, you must specify its position in the tree: whether it would be the first or the last node, whether you want to position it before or after a node of your choice, etc. For example, if you want to add a new element to a document, the element would be considered a child of the root, that is, a child of the XmlDocument.DocumentElement property.
To support the positions of existing nodes, the XmlNode class, which is the ancestor to all XML nodes of the .NET Framework, provides various methods. One of these methods is named AppendChild. It is used to add an element as the last child of its parent. The syntax of the XmlNode.AppendChild() method is:
Public Overridable Function AppendChild(ByVal newChild As XmlNode) As XmlNode
When calling this method, pass the XmlNode object you had previous created. After adding the node, if you want to keep it, you should save the file. Here is an example:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click
Dim xeRoot As XmlElement
Dim xeHouseType As XmlElement
Dim xdHouseTypes As New XmlDocument()
Dim strHouseTypesFile = Server.MapPath("exercises/HouseTypes.xml")
xdHouseTypes.Load(strHouseTypesFile)
xeRoot = xdHouseTypes.DocumentElement
xeHouseType = xdHouseTypes.CreateElement("category")
xeRoot.AppendChild(xeHouseType)
xdHouseTypes.Save(strHouseTypesFile)
End Sub
</script>
<title>Altair Realtors - House Type</title>
</head>
<body>
<h3>Altair Realtors - House Type</h3>
<form id="frmHouseTypes" runat="server">
<asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<house-types>
<category>Condominium</category>
<category />
</house-types>
In the previous code, we assumed that the primary XML file had already been created. If the file cannot be found, the server would produce an error. Therefore, in most cases, you should first check whether the file exists. This can be done as follows:
<%@ Page Language="VB" %> <%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click Dim xeHouseType As XmlElement Dim xdHouseTypes As New XmlDocument() Dim strHouseTypesFile = Server.MapPath("exercises/HouseTypes.xml") If File.Exists(strHouseTypesFile) Then xdHouseTypes.Load(strHouseTypesFile) xeHouseType = xdHouseTypes.CreateElement("category") xdHouseTypes.DocumentElement.AppendChild(xeHouseType) xdHouseTypes.Save(strHouseTypesFile) End If End Sub </script> <title>Altair Realtors - House Type</title> </head> <body> <h3>Altair Realtors - House Type</h3> <form id="frmHouseTypes" runat="server"> <asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button> </form> </body> </html>
The above code would create a new element only if the file exists already. If there is no such a file, nothing would happen. If you want, after chcking the existense of the file, if it doesn't exist, you can first create it, and then add the new element to it. This can be done as follows:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click
Dim xeHouseType As XmlElement
Dim xdHouseTypes As New XmlDocument()
Dim strHouseTypesFile = Server.MapPath("exercises/HouseTypes.xml")
' If the XML file doesn't exist, create it
If File.Exists(strHouseTypesFile) Then
xdHouseTypes.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" &
"<house-types></house-types>")
xdHouseTypes.Save(strHouseTypesFile)
End If
' Now that the XML file exists, open
xdHouseTypes.Load(strHouseTypesFile)
xeHouseType = xdHouseTypes.CreateElement("category")
xdHouseTypes.DocumentElement.AppendChild(xeHouseType)
xdHouseTypes.Save(strHouseTypesFile)
End Sub
</script>
<title>Altair Realtors - House Type</title>
</head>
<body>
<h3>Altair Realtors - House Type</h3>
<form id="frmHouseTypes" runat="server">
<asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button>
</form>
</body>
</html>
Of course, you can check the existense of the file by its name or as a Stream-based object.
When creating a new element, one of your concerns is to specify what node will own the new element. As we know already, you can get a list of nodes that use a certain name by calling the XmlDocument.GetElementsByTagName() method. You can also locate an element using its position (or index) in the collection of nodes. You can then decide whether the new element will be a child of that node. This can be done by simply calling the AppendChild() method on that node. Here is an example:
Road System Database: roads1.xml
<?xml version="1.0" encoding="utf-8"?> <roads> <road> <road-name>MD 410</road-name> <road-type>Road</road-type> <distance>13.920</distance> <location>From East Bethesda to Pennsy Drive in Landover Hills</location> </road> <road> <road-name>I-81</road-name> <road-type>Interstate</road-type> <distance>855</distance> <location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location> </road> <road> <road-name>US 75</road-name> <road-type>Road</road-type> <distance>1239</distance> <location>From Dallas, TX to Moorhead, MN</location> </road> </roads>
Road System Database: newroad.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click
Dim i As Integer
Dim xnlRoads As XmlNodeList
Dim xeIntersection As XmlElement
Dim xdRoads As New XmlDocument()
Dim strRoadsFile = Server.MapPath("roads1.xml")
xdRoads.Load(strRoadsFile)
xnlRoads = xdRoads.DocumentElement.ChildNodes
xeIntersection = xdRoads.CreateElement("intersection")
For i = 0 To xnlRoads.Count - 1
If xnlRoads(i)("road-name").InnerText = "I-81"
xnlRoads(i).AppendChild(xeIntersection)
xdRoads.Save(strRoadsFile)
End If
Next
End Sub
</script>
<title>Road System Database - New Road</title>
</head>
<body>
<h3>Road System Database - New Road</h3>
<form id="frmRoads" runat="server">
<asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<roads>
<road>
<road-name>MD 410</road-name>
<road-type>Road</road-type>
<distance>13.920</distance>
<location>From East Bethesda to Pennsy Drive in Landover Hills</location>
</road>
<road>
<road-name>I-81</road-name>
<road-type>Interstate</road-type>
<distance>855</distance>
<location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location>
<intersection />
</road>
<road>
<road-name>US 75</road-name>
<road-type>Road</road-type>
<distance>1239</distance>
<location>From Dallas, TX to Moorhead, MN</location>
</road>
</roads>
or you can decide that the new node would be created on the same level as the node, or on the same level as parent node, etc. Here is an example that adds a new element to a node gotten from its index and XML element name:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateElementClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateElement.Click
Dim i As Integer
Dim xeRoad As XmlElement
Dim xnlRoads As XmlNodeList
Dim xdRoads As New XmlDocument()
Dim strRoadsFile = Server.MapPath("roads1.xml")
xdRoads.Load(strRoadsFile)
xnlRoads = xdRoads.DocumentElement.ChildNodes
xeRoad = xdRoads.CreateElement("road")
For i = 0 To xnlRoads.Count - 1
If xnlRoads(i)("road-name").InnerText = "I-81"
xnlRoads(i).ParentNode.AppendChild(xeRoad)
xdRoads.Save(strRoadsFile)
End If
Next
End Sub
</script>
<title>Road System Database - New Road</title>
</head>
<body>
<h3>Road System Database - New Road</h3>
<form id="frmRoads" runat="server">
<asp:Button id="btnCreateElement" Text="Create XML Element" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<roads>
<road>
<road-name>MD 410</road-name>
<road-type>Road</road-type>
<distance>13.920</distance>
<location>From East Bethesda to Pennsy Drive in Landover Hills</location>
</road>
<road>
<road-name>I-81</road-name>
<road-type>Interstate</road-type>
<distance>855</distance>
<location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location>
<intersection />
</road>
<road>
<road-name>US 75</road-name>
<road-type>Road</road-type>
<distance>1239</distance>
<location>From Dallas, TX to Moorhead, MN</location>
</road>
<road />
</roads>
Adding the Inner Text of an Element
We already know that the XmlNode.InnerXml property includes a node, its markup, its child(ren) and their markup. This means that you can create the child node(s) with its (their) markup(s) as a string and assign that string to an XmlNode.InnerXml property:
Public Overridable Property InnerXml As String
Here is an example:
Watts A Loan: ne.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Sub btnCreateClick(ByVal sender As Object, ByVal e As EventArgs)
Dim xeEmployee As XmlElement
Dim xdEmployees As New XmlDocument()
Dim strEmployeesFile = Server.MapPath("employees.xml")
' Find out if the file exists already. If it doesn't, then create it
If Not File.Exists(strEmployeesFile) Then
Using fsEmployees As New FileStream(strEmployeesFile, FileMode.CreateNew, FileAccess.Write, FileShare.Write)
xdEmployees.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" &
"<employees></employees>")
xdEmployees.Save(fsEmployees)
End Using
End If
' At this time, we have an Employees.xml file. Open it
Using fsEmployees As New FileStream(strEmployeesFile, FileMode.Open, FileAccess.Read, FileShare.Read)
xdEmployees.Load(fsEmployees)
End Using
If String.IsNullOrEmpty(txtEmployeeNumber.Text) Then
lblMessage.Text = "You must provide an employee number."
Exit Sub
End If
If String.IsNullOrEmpty(txtLastName.Text) Then
lblMessage.Text = "You must provide the employee's last name."
Exit Sub
End If
' Create an element named Employee
xeEmployee = xdEmployees.CreateElement("Employee")
' Create the XML code of the child element of Tenant
xeEmployee.InnerXml = "<EmployeeNumber>" & txtEmployeeNumber.Text & "</EmployeeNumber>" &
"<FirstName>" & txtFirstName.Text & "</FirstName>" &
"<LastName>" & txtLastName.Text & "</LastName>" &
"<Title>" & txtTitle.Text & "</Title>"
' Append the new element as a child of employees
xdEmployees.DocumentElement.AppendChild(xeEmployee)
' Save the XML file
Using fsEmployees As New FileStream(strEmployeesFile, FileMode.Create, FileAccess.Write, FileShare.Write)
xdEmployees.Save(fsEmployees)
Response.Redirect("index.aspx")
End Using
End Sub
</script>
<style>
#container
{
margin: auto;
width: 500px;
}
</style>
<title>Lambda Square Apartments - New Employee</title>
</head>
<body>
<form id="frmEmployee" runat="server">
<div id="container">
<h3>Lambda Square Apartments - New Employee</h3>
<table>
<tr>
<td><b>Employee #:</b></td>
<td><asp:TextBox id="txtEmployeeNumber" style="width: 65px" runat="server"></asp:TextBox></td>
<td> </td>
<td> </td>
</tr>
<tr>
<td><b>First Name:</b></td>
<td><asp:TextBox id="txtFirstName" style="width: 65px;" runat="server"></asp:TextBox></td>
<td><b>Last Name:</b></td>
<td><asp:TextBox id="txtLastName" style="width: 65px;" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><b>Title:</b></td>
<td colspan="3"><asp:TextBox id="txtTitle" style="width: 250px;" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> </td>
<td><asp:Button id="btnCreate" Text="Create" Width="75px"
OnClick="btnCreateClick" runat="server"></asp:Button></td>
</tr>
</table>
</div>
<asp:Label id="lblMessage" runat="server"></asp:Label>
</form>
</body>
</html>
In the same way, you can provide the whole structure of an element including its children. Here is an example:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateRoadClick(ByVal sender As Object, ByVal e As EventArgs) Handles btnCreateRoad.Click
Dim xeRoad As XmlElement
Dim xdRoads As New XmlDocument()
Dim strRoadsFile = Server.MapPath("roads3.xml")
If Not File.Exists(strRoadsFile) Then
xdRoads.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" &
"<roads />")
xdRoads.Save(strRoadsFile)
End If
xdRoads.Load(strRoadsFile)
xeRoad = xdRoads.CreateElement("road")
xeRoad.InnerXml = "<road-name>WYO 789</road-name>" &
"<road-type>State Highway</road-type>" &
"<distance>404</distance>" &
"<location>From Colorado to Montana</location>" &
"<intersections>" &
" <intersection>" &
" <intersecting>SH 13</intersecting>" &
" <in-near>Baggs, CO</in-near>" &
" </intersection>" &
" <intersection>" &
" <intersecting>I-80/US 30</intersecting>" &
" <in-near>Creston Junction</in-near>" &
" </intersection>" &
" <intersection>" &
" <intersecting>US 287</intersecting>" &
" <in-near>Rawlins, WY</in-near>" &
" </intersection>" &
"</intersections>"
xdRoads.DocumentElement.AppendChild(xeRoad)
xdRoads.Save(strRoadsFile)
End Sub
</script>
<title>Road System Database - New Road</title>
</head>
<body>
<h3>Road System Database - New Road</h3>
<form id="frmRoads" runat="server">
<asp:Button id="btnCreateRoad" Text="Create Road" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<roads>
<road>
<road-name>WYO 789</road-name>
<road-type>State Highway</road-type>
<distance>404</distance>
<location>From Colorado to Montana</location>
<intersections>
<intersection>
<intersecting>SH 13</intersecting>
<in-near>Baggs, CO</in-near>
</intersection>
<intersection>
<intersecting>I-80/US 30</intersecting>
<in-near>Creston Junction</in-near>
</intersection>
<intersection>
<intersecting>US 287</intersecting>
<in-near>Rawlins, WY</in-near>
</intersection>
</intersections>
</road>
</roads>
Remember that if you want to add the new element to a node other than the root, you have to specify that parent node.
Adding an Element With Value
Consider the following XML file named videos1.xml:
<?xml version="1.0" encoding="utf-8" ?> <videos> <title>The Distinguished Gentleman</title> </videos>
If you want the element to have a value, the XmlDocument class provides the CreateTextNode() method. This method returns an XmlText value. The syntax of this method is:
Public Overridable Function CreateTextNode(ByVal text As String) As XmlText
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. Calling this method on the LastChild node of the one that called the AppendChild() method would specify the value of the new node. Here is an example:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Video Collection</title>
</head>
<body>
<h3>Video Collection</h3>
<%
Dim xdVideoCollection As New XmlDocument()
Dim strFileName = Server.MapPath("exercises/videos1.xml")
Using fsVideo As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
xdVideoCollection.Load(fsVideo)
End Using
Using fsVideo As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
Dim xeRoot As XmlElement = xdVideoCollection.DocumentElement
Dim xeVideo As XmlElement = xdVideoCollection.CreateElement("title")
Dim txtvideo As XmlText = xdVideoCollection.CreateTextNode("Basic Instinct")
xeRoot.AppendChild(xeVideo)
xeRoot.LastChild.AppendChild(txtvideo)
xdVideoCollection.Save(fsVideo)
End Using
%>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<title>The Distinguished Gentleman</title>
<title>Basic Instinct</title>
</videos>
Consider the following XML file named "chemistry1.xml":
<?xml version="1.0" encoding="utf-8"?> <chemistry> <element> <name>Hydrogen</name> </element> <element> <name>Helium</name> </element> </chemistry>
Notice that the root, chemistry, has a repetitive child named element. This element element has its own child named name. Imagine that you want to add a new element node that has a child. To do this, first create an empty element node as a child of the root (we learned earlier how to do that). 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:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Chemistry</title>
</head>
<body>
<h3>Chemistry</h3>
<%
Dim xtElement As XmlText
Dim xeRoot As XmlElement
Dim xeElement As XmlElement
Dim xdChemistry As New XmlDocument()
Dim strFileName = Server.MapPath("exercises/chemistry1.xml")
Using fsChemistry As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
xdChemistry.Load(fsChemistry)
End Using
Using fsChemistry As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
xeRoot = xdChemistry.DocumentElement
xeElement = xdChemistry.CreateElement("symbol")
xtElement = xdChemistry.CreateTextNode("He")
xeRoot.LastChild.AppendChild(xeElement)
xeRoot.LastChild.LastChild.AppendChild(xtElement)
xdChemistry.Save(fsChemistry)
End Using
%>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<chemistry>
<element>
<name>Hydrogen</name>
</element>
<element>
<name>Helium</name>
<symbol>He</symbol>
</element>
</chemistry>
The combination of calls to XmlDocument.CreateElement() and XmlDocument.CreateTextNode() allow you to create a new element that has a value. As done above, you can keep using that combination to create a new element and its child nodes. Here are examples:
Lambda Square Apartments: ne.aspx
<%@ Page Language="VB" %> <%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Xml" %> <!DOCTYPE html> <html> <head runat="server"> <script runat="server"> Sub btnCreateClick(ByVal sender As Object, ByVal e As EventArgs) Dim xtEmployee As XmlText Dim xeEmployee As XmlElement Dim xdEmployees As New XmlDocument() ' This is the XML file that holds the list of employees Dim strFileName = Server.MapPath("employees.xml") ' Find out if the file exists already. If it doesn't, then create it If Not File.Exists(strFileName) Then xdEmployees.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" & "<employees></employees>") xdEmployees.Save(strFileName) End If ' Open the XML file. xdEmployees.Load(strFileName) ' Create an element named employee xeEmployee = xdEmployees.CreateElement("employee") xdEmployees.DocumentElement.AppendChild(xeEmployee) ' Create a child node named employee-number xeEmployee = xdEmployees.CreateElement("employee-number") ' Create the value of the new element xtEmployee = xdEmployees.CreateTextNode(txtEmployeeNumber.Text) ' Add the new element as a child of the <employee> element xdEmployees.DocumentElement.LastChild.AppendChild(xeEmployee) ' Specify the value of the new element xdEmployees.DocumentElement.LastChild.LastChild.AppendChild(xtEmployee) xeEmployee = xdEmployees.CreateElement("first-name") xtEmployee = xdEmployees.CreateTextNode(txtFirstName.Text) xdEmployees.DocumentElement.LastChild.AppendChild(xeEmployee) xdEmployees.DocumentElement.LastChild.LastChild.AppendChild(xtEmployee) xeEmployee = xdEmployees.CreateElement("last-name") xtEmployee = xdEmployees.CreateTextNode(txtLastName.Text) xdEmployees.DocumentElement.LastChild.AppendChild(xeEmployee) xdEmployees.DocumentElement.LastChild.LastChild.AppendChild(xtEmployee) xeEmployee = xdEmployees.CreateElement("title") xtEmployee = xdEmployees.CreateTextNode(txtTitle.Text) xdEmployees.DocumentElement.LastChild.AppendChild(xeEmployee) xdEmployees.DocumentElement.LastChild.LastChild.AppendChild(xtEmployee) 'Save the XML file xdEmployees.Save(strFileName) ' Close the current webpage and go to the home page Server.Transfer("index.aspx") End Sub </script> <style> #container { margin: auto; width: 500px; } </style> <title>Lambda Square Apartments - New Employee</title> </head> <body> <form id="frmEmployee" runat="server"> <div id="container"> <h3>Lambda Square Apartments - New Employee</h3> <table> <tr> <td><b>Employee #:</b></td> <td><asp:TextBox id="txtEmployeeNumber" style="width: 65px" runat="server"></asp:TextBox></td> <td> </td> <td> </td> </tr> <tr> <td><b>First Name:</b></td> <td><asp:TextBox id="txtFirstName" style="width: 65px;" runat="server"></asp:TextBox></td> <td><b>Last Name:</b></td> <td><asp:TextBox id="txtLastName" style="width: 65px;" runat="server"></asp:TextBox></td> </tr> <tr> <td><b>Title:</b></td> <td colspan="3"><asp:TextBox id="txtTitle" style="width: 250px;" runat="server"></asp:TextBox></td> </tr> <tr> <td> </td> <td> </td> <td> </td> <td><asp:Button id="btnCreate" Text="Create" Width="75px" OnClick="btnCreateClick" runat="server"></asp:Button></td> </tr> </table> </div> </form> </body> </html>
Using the same approach, you can add children to children of children, and so on.
Inserting an Element
Adding an Element as the First Child
To let you add a new element and position it as the first in an XML document, the XmlElement class is equipped with a method named PrependChild. Its syntax is:
Public Overridable Function PrependChild(ByVal newChild As XmlNode) As XmlNode
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:
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Sub btnSubmitClick(ByVal sender As Object, ByVal e As EventArgs)
Dim unitPrice As Double = 0.0
Dim xdAutoParts = New XmlDocument()
Dim strAutoPartsFile = Server.MapPath("AutoParts.xml")
If String.IsNullOrEmpty(txtPartNumber.Text) Then
lblMessage.Text = "You must specify a part number for the auto-part."
Exit Sub
End If
If String.IsNullOrEmpty(txtYear.Text) Then
lblMessage.Text = "You must specify the year of the car."
Exit Sub
End If
If String.IsNullOrEmpty(txtMake.Text) Then
lblMessage.Text = "You must specify the car manufacturer."
Exit Sub
End If
If String.IsNullOrEmpty(txtModel.Text) Then
lblMessage.Text = "You must specify the car model."
Exit Sub
End If
If String.IsNullOrEmpty(txtPartName.Text) Then
lblMessage.Text = "You must enter the name of the part."
Exit Sub
End If
If String.IsNullOrEmpty(txtUnitPrice.Text) Then
lblMessage.Text = "You must enter the unit price of the part."
Exit Sub
End If
Try
unitPrice = CDbl(txtUnitPrice.Text)
Catch fexc As FormatException
lblMessage.Text = "Invalid Unit Price."
End Try
If Not File.Exists(strAutoPartsFile) Then
Using fsAutoParts = New FileStream(strAutoPartsFile, FileMode.Create, FileAccess.Write)
xdAutoParts.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" &
"<auto-parts></auto-parts>")
xdAutoParts.Save(fsAutoParts)
End Using
End If
Using fsAutoParts As FileStream = New FileStream(strAutoPartsFile, FileMode.Open, FileAccess.Read)
xdAutoParts.Load(fsAutoParts)
End Using
Using fsAutoParts = New FileStream(strAutoPartsFile, FileMode.Create, FileAccess.Write)
Dim xeAutoPart = xdAutoParts.CreateElement("AutoPart")
xeAutoPart.InnerXml = "<part-number>" & txtPartNumber.Text & "</part-number>" &
"<vehicle-year>" & txtYear.Text & "</vehicle-year>" &
"<make>" & txtMake.Text & "</make>" &
"<model>" & txtModel.Text & "</model>" &
"<category>" & txtCategory.Text & "</category>" &
"<part-name>" & txtPartName.Text & "</part-name>" &
"<unit-price>" & unitPrice & "</unit-price>"
xdAutoParts.DocumentElement.PrependChild(xeAutoPart)
xdAutoParts.Save(fsAutoParts)
End Using
txtPartNumber.Text = ""
txtYear.Text = ""
txtMake.Text = ""
txtModel.Text = ""
txtCategory.Text = ""
txtPartName.Text = ""
txtUnitPrice.Text = "0.00"
End Sub
</script>
<style>
#container
{
margin: auto;
width: 500px;
}
</style>
<title>College Park Auto Parts - New Auto Part</title>
</head>
<body>
<form id="frmAutoPart" runat="server">
<div id="container">
<h3>College Park Auto Parts - New Auto Part</h3>
<table>
<tr>
<td><b>Part #:</b></td>
<td><asp:TextBox id="txtPartNumber" style="width: 55px" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><b>Year:</b></td>
<td><asp:TextBox id="txtYear" style="width: 55px" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td>Make</td>
<td><asp:TextBox id="txtMake" style="width: 105px" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><b>Model:</b></td>
<td><asp:TextBox id="txtModel" style="width: 150px;" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><b>Category:</b></td>
<td><asp:TextBox id="txtCategory" style="width: 150px;" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><b>Part Name:</b></td>
<td><asp:TextBox id="txtPartName" style="width: 300px;" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td><b>Unit Price:</b></td>
<td><asp:TextBox id="txtUnitPrice" style="width: 85px;" Text="0.00" runat="server"></asp:TextBox>
<asp:Button id="btnSubmit" Text="Submit" Width="75px"
OnClick="btnSubmitClick" runat="server"></asp:Button></td>
</tr>
</table>
</div>
<asp:Label id="lblMessage" runat="server"></asp:Label>
</form>
</body>
</html>
Adding an Element as a Last Child
As we have seen in previous sections, to add an element as the last node of an element, create an XmlElement object and call the AppendChild() method.
Inserting an Element Referencing a Sibling
Instead of simply adding a new node at the end of child nodes, 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 Overridable Function InsertBefore(ByVal newChild As XmlNode, ByVal refChild As XmlNode) As XmlNode
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.
You can add a new node to position it after a known element. To support this, the XmlNode class is equipped with a method named InsertAfter. Its syntax is:
Public Overridable Function InsertAfter(ByVal newChild As XmlNode, ByVal refChild As XmlNode) As XmlNode
As a result, using one of these methods, you can add children of an existing node after locating that node. Here is an example:
Road System Database: roads.xml
<?xml version="1.0" encoding="utf-8"?> <roads> <road> <road-name>MD 410</road-name> <road-type>Road</road-type> <distance>13.920</distance> <location>From East Bethesda to Pennsy Drive in Landover Hills</location> </road> <road> <road-name>I-81</road-name> <road-type>Interstate</road-type> <distance>855</distance> <location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location> </road> <road> <road-name>US 75</road-name> <road-type>Road</road-type> <distance>1239</distance> <location>From Dallas, TX to Moorhead, MN</location> </road> </roads>
Road System Database: intersection.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateIntersectionClick(ByVal sender As Object, ByVal e As EventArgs)
Dim xeRoad As XmlElement
Dim xnRoad, xnChild As XmlNode
Dim xdRoads As New XmlDocument()
Dim xnlRoads, xnlChildren As XmlNodeList
Dim strRoadsFile = Server.MapPath("roads1.xml")
If File.Exists(strRoadsFile) Then
Using fsRoad As New FileStream(strRoadsFile, FileMode.Open, FileAccess.Read)
xdRoads.Load(strRoadsFile)
End Using
' Create a list of nodes whose name is Title
xnlRoads = xdRoads.GetElementsByTagName("road")
Using fsRoad As New FileStream(strRoadsFile, FileMode.Create, FileAccess.Write)
' Now you can check each node of the list
For Each xnRoad in xnlRoads
' Within a Road, create a list of its children
xnlChildren = xnRoad.ChildNodes
' Visit each child node
For Each xnChild in xnlChildren
' If the child node, the road name, is I-81
If xnChild.InnerText = "I-81" Then
' Create an element named intersection
xeRoad = xdRoads.CreateElement("intersection")
' Specify the text of the new element
xeRoad.InnerText = "I-77"
' Insert the new node below the selected one
xnRoad.InsertAfter(xeRoad, xnChild)
' Save the file
xdRoads.Save(fsRoad)
Exit Sub
End If
Next
Next
End Using
End If
End Sub
</script>
<title>Road System Database - New Intersecting Road</title>
</head>
<body>
<h3>Road System Database - New Intersecting Road</h3>
<form id="frmRoads" runat="server">
<asp:Button id="btnCreateIntersection" Text="Create Intersecting Road"
OnClick="btnCreateIntersectionClick" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<roads>
<road>
<road-name>MD 410</road-name>
<road-type>Road</road-type>
<distance>13.920</distance>
<location>From East Bethesda to Pennsy Drive in Landover Hills</location>
</road>
<road>
<road-name>I-81</road-name>
<intersection>I-77</intersection>
<road-type>Interstate</road-type>
<distance>855</distance>
<location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location>
</road>
<road>
<road-name>US 75</road-name>
<road-type>Road</road-type>
<distance>1239</distance>
<location>From Dallas, TX to Moorhead, MN</location>
</road>
</roads>
Of course, you use the second argument to specify the node that will precede the new element. You can use the XmlNode.NextSibling property to skip an element. Here is an example:
Road System Database: roads.xml
<?xml version="1.0" encoding="utf-8"?> <roads> <road> <road-name>MD 410</road-name> <road-type>Road</road-type> <distance>13.920</distance> <location>From East Bethesda to Pennsy Drive in Landover Hills</location> </road> <road> <road-name>I-81</road-name> <road-type>Interstate</road-type> <distance>855</distance> <location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location> </road> <road> <road-name>US 75</road-name> <road-type>Road</road-type> <distance>1239</distance> <location>From Dallas, TX to Moorhead, MN</location> </road> </roads>
Road System Database: intersection.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<script runat="server">
Private Sub btnCreateIntersectionClick(ByVal sender As Object, ByVal e As EventArgs)
Dim xeRoad As XmlElement
Dim xnRoad, xnChild As XmlNode
Dim xdRoads As New XmlDocument()
Dim xnlRoads, xnlChildren As XmlNodeList
Dim strRoadsFile = Server.MapPath("roads1.xml")
If File.Exists(strRoadsFile) Then
Using fsRoad As New FileStream(strRoadsFile, FileMode.Open, FileAccess.Read)
xdRoads.Load(strRoadsFile)
End Using
' Create a list of nodes whose name is Title
xnlRoads = xdRoads.GetElementsByTagName("road")
Using fsRoad As New FileStream(strRoadsFile, FileMode.Create, FileAccess.Write)
' Now you can check each node of the list
For Each xnRoad in xnlRoads
' Within a Road, create a list of its children
xnlChildren = xnRoad.ChildNodes
' Visit each child node
For Each xnChild in xnlChildren
' If the child node, the road name, is I-81
If xnChild.InnerText = "I-81" Then
' Create an element named intersection
xeRoad = xdRoads.CreateElement("intersection")
' Specify the text of the new element
xeRoad.InnerText = "I-77"
' Insert the new node below the selected one
xnRoad.InsertAfter(xeRoad, xnChild.NextSibling.NextSibling.NextSibling)
' Save the file
xdRoads.Save(fsRoad)
Exit Sub
End If
Next
Next
End Using
End If
End Sub
</script>
<title>Road System Database - New Intersecting Road</title>
</head>
<body>
<h3>Road System Database - New Intersecting Road</h3>
<form id="frmRoads" runat="server">
<asp:Button id="btnCreateIntersection" Text="Create Intersecting Road"
OnClick="btnCreateIntersectionClick" runat="server"></asp:Button>
</form>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<roads>
<road>
<road-name>MD 410</road-name>
<road-type>Road</road-type>
<distance>13.920</distance>
<location>From East Bethesda to Pennsy Drive in Landover Hills</location>
</road>
<road>
<road-name>I-81</road-name>
<road-type>Interstate</road-type>
<distance>855</distance>
<location>From Dandridge, TN to Wellesley Island, NY/Hill Island, ON</location>
<intersection>I-77</intersection>
</road>
<road>
<road-name>US 75</road-name>
<road-type>Road</road-type>
<distance>1239</distance>
<location>From Dallas, TX to Moorhead, MN</location>
</road>
</roads>
Updating an Element
Introduction
The .NET Framework implementation of XML provides various options to change the aspect, the structure, and/or the value(s), of an element. For example, you can use the same logic used in collection classes. This consists of locating a node and simply changing its value(s), then saving the file. Here is an example:
employees.xml
<?xml version="1.0" encoding="UTF-8"?> <employees> <employee> <employee-number>294-075</employee-number> <first-name>Frank</first-name> <last-name>Douglas</last-name> <title>Company Owner</title> </employee> <employee> <employee-number>831-419</employee-number> <first-name>Patricia</first-name> <last-name>Jeffers</last-name> <title>Sales Representative</title> </employee> <employee> <employee-number>277-397</employee-number> <first-name>Paul</first-name> <last-name>Bottoms</last-name> <title>Accountant</title> </employee> </employees>
editemployee.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Exercise</title>
</head>
<body>
<h3>Exercise</h3>
<%
Dim xnEmployee As XmlNode
Dim xeEmployee As XmlElement
Dim xnlEmployees As XmlNodeList
Dim xdEmployees As New XmlDocument()
Dim strFileName = Server.MapPath("exercises/employees.xml")
Using fsEmployees As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
xdEmployees.Load(fsEmployees)
End Using
xnlEmployees = xdEmployees.GetElementsByTagName("employee-number")
Using fsEmployees As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
For Each xnEmployee in xnlEmployees
If xnEmployee.InnerText = "831-419" Then
xnEmployee.ParentNode.InnerXml = "<employee-number>831-419</employee-number>" &
"<first-name>Patricia</first-name>" &
"<last-name>Jefferies</last-name>" &
"<title>Sales Representative</title>"
xdEmployees.Save(fsEmployees)
Exit For
End If
Next
End Using
%>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="UTF-8"?>
<employees>
<employee>
<employee-number>294-075</employee-number>
<first-name>Frank</first-name>
<last-name>Douglas</last-name>
<title>Company Owner</title>
</employee>
<employee>
<employee-number>831-419</employee-number>
<first-name>Patricia</first-name>
<last-name>Jefferies</last-name>
<title>Sales Representative</title>
</employee>
<employee>
<employee-number>277-397</employee-number>
<first-name>Paul</first-name>
<last-name>Bottoms</last-name>
<title>Accountant</title>
</employee>
</employees>
Replacing an Element
On the other hand, the XmlNode class is equipped with a method named ReplaceChild. Its syntax is:
Public Overridable Function ReplaceChild(ByVal newChild As XmlNode, ByVal oldChild As XmlNode) As XmlNode
To use this method, you can first create a new XmlNode. Then locate an existing element and get its reference. When you call this method, pass the new element as the first argument and pass the existing element as the second argument.
Deleting Elements
Deleting an Element
If you have a node you don't want or don't need anymore in a document, you can delete it. To let you delete a node, the XmlNode class provides the RemoveChild() method. Its syntax is:
Public Overridable Function RemoveChild(ByVal oldChild As XmlNode) As XmlNode
This method takes as argument the node to delete. If the node exists, it would be deleted and the method would return the node that was deleted. If the node does not exist, nothing would happen. Here is an example:
employees.xml:
<?xml version="1.0" encoding="UTF-8"?> <employees> <employee> <employee-number>294-075</employee-number> <first-name>Frank</first-name> <last-name>Douglas</last-name> <title>Company Owner</title> </employee> <employee> <employee-number>831-419</employee-number> <first-name>Patricia</first-name> <last-name>Jeffers</last-name> <title>Sales Representative</title> </employee> <employee> <employee-number>277-397</employee-number> <first-name>Paul</first-name> <last-name>Bottoms</last-name> <title>Accountant</title> </employee> </employees>
deleteemployee.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Exercise</title>
</head>
<body>
<h3>Exercise</h3>
<%
Dim xnEmployee As XmlNode
Dim xdEmployees As New XmlDocument()
Dim xnlEmployees, xnlChildren As XmlNodeList
Dim strFileName = Server.MapPath("exercises/employees.xml")
If File.Exists(strFileName) Then
Using fsEmployee As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
xdEmployees.Load(strFileName)
End Using
' Create a list of nodes whose name is Title
xnlEmployees = xdEmployees.GetElementsByTagName("employee")
Using fsEmployee As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
' visit each Employee
For Each xnEmployee In xnlEmployees
' Within a Employee, get a list of its children
xnlChildren = xnEmployee.ChildNodes
' Visit each child node
For Each xnChild In xnlChildren
' If the child node is Bruce Beresford
If xnChild.InnerText = "831-419" Then
xnEmployee.RemoveChild(xnChild)
xdEmployees.Save(fsEmployee)
End If
Next
Next
End Using
End If
%>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="UTF-8"?> <employees> <employee> <employee-number>294-075</employee-number> <first-name>Frank</first-name> <last-name>Douglas</last-name> <title>Company Owner</title> </employee> <employee> <first-name>Patricia</first-name> <last-name>Jeffers</last-name> <title>Sales Representative</title> </employee> <employee> <employee-number>277-397</employee-number> <first-name>Paul</first-name> <last-name>Bottoms</last-name> <title>Accountant</title> </employee> </employees>
Clearing an Element of its Children
To delete all child nodes of a node, you can call the XmlNode.RemoveAll() method. Its syntax is:
Public Overridable Sub RemoveAll
When called, this method will remove all child nodes, if any, of their parent node. Here is an example of calling it:
employees.xml
<?xml version="1.0" encoding="UTF-8"?> <employees> <employee> <employee-number>294-075</employee-number> <first-name>Frank</first-name> <last-name>Douglas</last-name> <title>Company Owner</title> </employee> <employee> <first-name>Patricia</first-name> <last-name>Jeffers</last-name> <title>Sales Representative</title> </employee> <employee> <employee-number>277-397</employee-number> <first-name>Paul</first-name> <last-name>Bottoms</last-name> <title>Accountant</title> </employee> </employees>
deleteallemployees.aspx
<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Exercise</title>
</head>
<body>
<h3>Exercise</h3>
<%
Dim xdEmployees As New XmlDocument()
Dim strFileName = Server.MapPath("exercises/employees.xml")
If File.Exists(strFileName) Then
Using fsEmployee As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
xdEmployees.Load(strFileName)
End Using
Using fsEmployee As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
xdEmployees.DocumentElement.RemoveAll()
xdEmployees.Save(fsEmployee)
End Using
End If
%>
</body>
</html>
This would produce:
<?xml version="1.0" encoding="utf-8"?> <employees> </employees>
|
||
Previous | Copyright © 2009-2016 FunctionX | Next |
|