Home

The Attributes of an XML Element

 

Fundamentals of Attributes

Introduction

When studying XML elements we saw how they constituted the main objects of an XML document. We also saw that an element could be nested inside of another element. Instead of nesting an element, you can make the nested element be the nesting element and thereby giving away its element qualities. This is the basis of an attribute.

An attribute is a value that is created as part of an element, making that value different from the value of a regular element. There are similarities and differences between an element and an attribute.

The element and the attribute have these in common:

The differences between an element and an attribute are:

To support attributes, the .NET Framework provides a class named XmlAttribute that is derived from XmlNode:

Public Class XmlAttribute
	Inherits XmlNode

Manually Creating an Attribute

Imagine you have an element, named street-address as a child of another element as follows:

<?xml version="1.0" encoding="utf-8"?>
<metro-system>
  <station>
    <street-address>15903 Somerville Drive</street-address>
  </station>
</metro-system>

An attribute must be created inside the start-tag of an element. To manually create an attribute, type the left angle bracket of the element, followed by the name of the element, an empty space, and the name of the attribute. The name follows the same rules we defined for names in XML.

An attribute should have a value that can be used to distinguish it. To specify the name of an attribute, assign a value as a string to its name. In the case of the above code fragment, since street-address is simply a child of the station element, you can change the street-address element to become an attribute of the station element as follows:

<?xml version="1.0" encoding="utf-8"?>
<metro-system>
  <station street-address="15903 Somerville Drive"></station>
</metro-system>

Now, street-address is an attribute of the station element.

The Collection of Attributes of an Element

Introduction

An element can have many different attributes. Here is an example:

<?xml version="1.0" encoding="utf-8"?>
<metro-system>
  <station street-address="15903 Somerville Drive"
	   city="Rockville" state="MD" ZipCode=20855>
    <identity>2014</identity>
    <name>Shady Grove</name>
    <line>
      <color>Red</color>
    </line>
    <daily-parking>1</daily-parking>
    <metered-parking>1</metered-parking>
  </station>
  <station street-address="192 19th St. SE"
	   city="Washington" state="DC" ZipCode=20003
	   parking="None"
           car-sharing="None">
    <identity>8640</identity>
    <name>Stadium-Armory</name>
    <line>
      <color>Orange</color>
      <color>Blue</color>
      <color>Silver</color>
    </line>
    <daily-parking>0</daily-parking>
    <metered-parking>0</metered-parking>
  </station>
</metro-system>

The attributes of an element are stored in a collection named XmlAttributeCollection. To support attributes, the XmlElement class is equipped with a property named Attributes:

Public Overrides ReadOnly Property Attributes As XmlAttributeCollection

Here is an example of starting to access the attributes of an element:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Metro System - Stations</title>
</head>
<body>

<h3>Metro System - Stations</h3>

<%
    Dim i As Integer
    Dim xaStation As XmlAttribute
    Dim xnlStations As XmlNodeList
    Dim xdStations As New XmlDocument()
    Dim strMetroFile = Server.MapPath("metro-system.xml")

    If File.Exists(strMetroFile) Then
        Using fsStations As New FileStream(strMetroFile, FileMode.Open, FileAccess.Read)
            xdStations.Load(fsStations)

            xnlStations = xdStations.GetElementsByTagName("station")

            For i = 0 To xnlStations.Count - 1
                For Each xaStation In xnlStations(i).Attributes
		    . . .
		Next
	    Next
	End Using
    End If
%>

</body>
</html>

The Number of Attributes in an Element

To know the number of attributes in an element, you can use the XmlNamedNodeMap.Count property:

Public Overridable ReadOnly Property Count As Integer

Accessing an XML Attribute

To access an attribute by its position in the collection, you can use the XmlNamedNodeMap.Item() method:

Public Overridable Function Item(ByVal index As Integer) As XmlNode

The XmlAttributeCollection class is equipped with an ItemOf indexed property. This property is overloaded in three versions. The first version has the following syntax:

Public ReadOnly Property ItemOf(ByVal i As Integer) As XmlAttribute

This property allows you to access an attribute by considering that the attributes are stored in an array. The first or most left attribute has an index of 0; the second attribute from left (of course without counting the name of the element) has an index of 1, and so on.

It can be difficult and sometimes unpredictable, in some scenarios, to access an attribute by its index because you must know exactly where each attribute is positioned. Consider the following version of our Videos.xml XML file:

<?xml version="1.0" encoding="utf-8" ?>
<videos FileDesc="Personal Video Collection">
    <video ISBN="0-7888-1623-3"
	   ScreenRatio="Standard"
	   SoundtrackAvailable="True">
        <title StoryBy="Marty Kaplan and Jonathan Reynold"
	       Screenplay="Marty Kaplan">The Distinguished Gentleman</title>
        <director>Jonathan Lynn</director>
        <actors></actors>
        <length>112 Minutes</length>
        <format>DVD</format>
        <rating>R</rating>
    </video>
    <video ISBN="0-7907-3900-3">
        <title Screenplay="Charlie Peter">Her Alibi</title>
        <director>Bruce Beresford</director>
        <length>94 Mins</length>
        <format>DVD</format>
        <rating>PG-13</rating>
    </video>
</videos>

In the first video, the name of the screenplay writer is stored at index 1. In the second video, the name of the screenplay writer is stored at index 0. In this case, it may not be a good idea to use the index to locate an attribute. Fortunately, the second version of the overloaded XmlAttributeCollection.ItemOf() property has the following syntax:

Public ReadOnly Property ItemOf(ByVal name As String) As XmlAttribute

With this version, you can explicitly specify the name of the attribute you want.

The Name of an Attribute

In the .NET Framework, an attribute is represented by the XmlAttribute class. Like all XML objects, this class is based on the XmlNode class. The name of an attribute is represented by its (read-only) Name property. Here is an example of accessing them:

Metro System: stations.xml

<?xml version="1.0" encoding="utf-8" ?>
<metro-system>
  <station street-address="15903 Somerville Drive"
	   city="Rockville" state="MD" ZipCode="20855">
    <identity>2014</identity>
    <name>Shady Grove</name>
    <line>
      <color>Red</color>
    </line>
    <daily-parking>1</daily-parking>
    <metered-parking>1</metered-parking>
  </station>
  <station street-address="192 19th St. SE"
	   city="Washington" state="DC" ZipCode="20003"
	   parking="None"
           car-sharing="None">
    <identity>8640</identity>
    <name>Stadium-Armory</name>
    <line>
      <color>Orange</color>
      <color>Blue</color>
      <color>Silver</color>
    </line>
    <daily-parking>0</daily-parking>
    <metered-parking>0</metered-parking>
  </station>
</metro-system>

Metro System: stations.aspx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Metro System - Stations</title>
</head>
<body>

<h3>Metro System - Stations</h3>

<%
    Dim i As Integer
    Dim xaStation As XmlAttribute
    Dim xnlStations As XmlNodeList
    Dim xdStations As New XmlDocument()
    Dim strMetroFile = Server.MapPath("App_Data/stations.xml")

    If File.Exists(strMetroFile) Then
        Using fsStations As New FileStream(strMetroFile, FileMode.Open, FileAccess.Read)
            xdStations.Load(fsStations)

            xnlStations = xdStations.GetElementsByTagName("station")

            For i = 0 To xnlStations.Count - 1
                For Each xaStation In xnlStations(i).Attributes
                    Response.Write("<br>" & xaStation.Name)
                Next
            Next
        End Using
    End If
%>

</body>
</html>

This would produce:

The Name of an Attribute

The Inner Text of an Attribute

The value of an attribute is represented by its Value property. Here is an example of accessing the values of attributes:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Metro System - Stations</title>
</head>
<body>

<h3>Metro System - Stations</h3>

<%
    Dim i As Integer
    Dim xaStation As XmlAttribute
    Dim xnlStations As XmlNodeList
    Dim xdStations As New XmlDocument()
    Dim strMetroFile = Server.MapPath("App_Data/stations.xml")

    If File.Exists(strMetroFile) Then
        Using fsStations As New FileStream(strMetroFile, FileMode.Open, FileAccess.Read)
            xdStations.Load(fsStations)

            xnlStations = xdStations.GetElementsByTagName("station")

            For i = 0 To xnlStations.Count - 1
                For Each xaStation In xnlStations(i).Attributes
                    Response.Write("<br>" & xaStation.Value)
                Next
            Next
        End Using
    End If
%>

</body>
</html>

This would produce:

The Value of an Attribute

The Inner Text and Inner Xml of an Attribute

Besides Value, you can also use XmlAttribute.InnerText or XmlAttribute.InnerXml to access the text of an attribute. Here is an example of accessing the text of attributes:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Metro System - Stations</title>
</head>
<body>

<h3>Metro System - Stations</h3>

<%
    Dim i As Integer
    Dim xaStation As XmlAttribute
    Dim xnlStations As XmlNodeList
    Dim xdStations As New XmlDocument()
    Dim strMetroFile = Server.MapPath("App_Data/stations.xml")

    If File.Exists(strMetroFile) Then
        Using fsStations As New FileStream(strMetroFile, FileMode.Open, FileAccess.Read)
            xdStations.Load(fsStations)

            xnlStations = xdStations.GetElementsByTagName("station")

            For i = 0 To xnlStations.Count - 1
                For Each xaStation In xnlStations(i).Attributes
                    Response.Write("<br>" & xaStation.InnerText)
                Next
            Next
        End Using
    End If
%>

</body>
</html>

Getting a Reference to an Attribute

Getting an Attribute as a Node

Many operations require that you get a reference to an attribute before proceeding. To assist you with this, the XmlElement class has a method named GetAttributeNode. Its syntax is:

Public Overridable Function GetAttributeNode(ByVal name As String) As XmlAttribute

Consider the following AutoParts.xml file:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part item-number="937418">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="LE" engine="1.8L L4" body-style="4-Speed Automatic Transaxle U341E">Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price status="New">58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price status="Refurbished">44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="SE" engine="2.0L L4 Gas" body-style="6-Speed Automatic Transaxle 6F">Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price status="New">14.15</unit-price>
  </auto-part>
</auto-parts>

Here is an example of calling this method:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<script runat="server">

</script>
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim xaBusiness As XmlAttribute
    Dim xdAutoParts As new XmlDocument()
    Dim strFileName = Server.MapPath("auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        
	     xaBusiness = xdAutoParts.DocumentElement.GetAttributeNode("business")

	     Response.Write("<br>Attribute Name = " & xaBusiness.Name)
	     Response.Write("<br>Value = " & xaBusiness.Value)
        End Using
    End If
%>
</body>
</html>

This would producce:

Getting a Reference to an Attribute

Getting an Attribute from an Element

Remember that the attributes of an element are stored in a collection. You can use that collection to locate a node, access its attributes, and then get a reference to the desired attribute. Here is an example:

Consider the following XML file named TimeZones.xml:

TimeZones.xml

<?xml version="1.0" encoding="utf-8" ?>
<time-zones>
  <zone>
    <name initials="CST">Central Standard Time</name>
    <utc>-06:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="West South Central" bea-region="Southeast">Arkansas</state>
      <state inclusion="Split" cb-region="South Atlantic" bea-region="Southeast">Florida</state>
      <state inclusion="Entirely" cb-region="West North Central" bea-region="Plains">Minnesota</state>
      <state inclusion="Entirely" cb-region="East North Central" bea-region="Great Lakes">Ohio</state>
    </states-and-territories>
  </zone>
  <zone>
    <name initials="EST">Eastern Standard Time</name>
    <utc>-05:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Maine</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Vermont</state>
      <state inclusion="Split" cb-region="South Atlantic" bea-region="Southeast">Florida</state>
    </states-and-territories>
  </zone>
</time-zones>

timezones.aspx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Time Zones</title>
</head>
<body>

<h3>Time Zones</h3>

<%
    Dim xnTimeZone As XmlNode
    Dim xaCharacteristic As XmlAttribute
    Dim xdTimeZones As New XmlDocument()
    Dim xnlTimeZones, xnlStates As XmlNodeList
    Dim strFileName = Server.MapPath("exercises/TimeZones.xml")

    If File.Exists(strFileName) Then
        Using fsTimeZones As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdTimeZones.Load(fsTimeZones)

	    ' Get a list of elements whose names are "name"
            xnlTimeZones = xdTimeZones.GetElementsByTagName("name")
        
	    ' Visit each time zone element
	    For Each xnTimeZone In xnlTimeZones
		' Look for a time zone named Eastern Standard Time
		If xnTimeZone.InnerText = "Eastern Standard Time" Then
		    ' Get a list of the third siblings of that node. This represents the states
		    xnlStates = xnTimeZone.NextSibling.NextSibling.ChildNodes

		    ' Visit each state
		    For Each xnState In xnlStates
			' Look for a state named Florida
			If xnState.InnerText = "Florida" Then
			    ' Get its attributes
			    For Each xaCharacteristic In xnState.Attributes
				Response.Write("<br>Attribute: Name = " & xaCharacteristic.Name)
				Response.Write("<br>Value: " & xaCharacteristic.Value)
			    Next
			End If
		    Next
		End If
	    Next
	End Using
    End If
%>
</body>
</html>

This would produce:

Getting an Attribute from an Element

Operations on an XML Attribute

Checking Whether an Element Has Attributes

To let you find out whether an element has at least one attribute, the XmlElement class is equipped with a method named HasAttributes. Its syntax is:

Public Overridable ReadOnly Property HasAttributes As Boolean

Consider the following XML file: roads.xml:

<?xml version="1.0" encoding="utf-8" ?>
<roads>
  <road>
    <road-name length-rank="1">I-90</road-name>
    <road-type>Interstate</road-type>
    <distance km="4861.09">3020.54</distance>
    <location>From the Edgar Martinez Drv South to Boston, MA</location>
    <intersections>
      <intersection>
        <intersecting>SR 519</intersecting>
        <in-near>Seattle, WA</in-near>
      </intersection>
      <intersection>
        <intersecting>I-5</intersecting>
        <in-near>Seattle, WA</in-near>
      </intersection>
    </intersections>
  </road>
  <road>
    <road-name length-rank="4">I-10</road-name>
    <road-type>Interstate</road-type>
    <distance km="3959.53">2460.34</distance>
    <location>From SR-1 (California State Route 1) to I-95 in Jacksonville, FL</location>
    <intersections>
      <intersection>
        <intersecting>SR 1</intersecting>
        <in-near>Santa Monica, CA</in-near>
      </intersection>
      <intersection>
        <intersecting>I-5</intersecting>
        <in-near>Los Angeles, CA</in-near>
      </intersection>
    </intersections>
  </road>
</roads>

Here is an example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Road System Database</title>
</head>
<body>

<h3>Road System Database</h3>

<%
    Dim xnRoad As XmlNode
    Dim xnlRoads As XmlNodeList
    Dim strFileName = Server.MapPath("App_Data/roads.xml")
    Dim xdRoads As New XmlDocument()

    If File.Exists(strFileName) Then
        Using fsRoads = New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdRoads.Load(fsRoads)

            ' Get a list of elements whose names are "road-name"
            xnlRoads = xdRoads.GetElementsByTagName("road-name")

            ' Visit each road element
            For Each xnRoad In xnlRoads
                ' Look for a road named I-10
                If xnRoad.InnerText = "I-10" Then
                    If CType(xnRoad, XmlElement).HasAttributes = True Then
                        Response.Write("<br>Road " & xnRoad.InnerText & " has at least one attribute.")
                    Else
                        Response.Write("<br>Road " & xnRoad.InnerText & " ain't got no attribute(s).")
                    End If
                End If

                If CType(xnRoad.NextSibling, XmlElement).HasAttributes = True Then
                    Response.Write("<br>Road Type " & xnRoad.NextSibling.InnerText & " has at least one attribute.")
                Else
                    Response.Write("<br>Road Type " & xnRoad.NextSibling.InnerText & " ain't got no attribute(s).")
                End If
            Next
        End Using
    End If
%>
</body>
</html>

Here is an example of running the program:

Checking Whether an Element Has Attributes

Adding an Attribute to an Element

An element can have 0, one, or more attributes. The attributes of an element are stored in the Attributes property of an XmlElement object. The XmlElement.Attributes property is based on a class called XmlAttributeCollection. The XmlAttributeCollection class is based on the XmlNamedNodeMap class.

Before performing an attribute-related operation on an element, to find out whether the element has any attribute, you can check the value of the Boolean HasAttributes property of its XmlElement element. If this property produces a true value, then the element has at least one attribute; otherwise, the element doesn't have any.

While a certain element may have an attribute, a sibling element with the same name may not have an attribute or may have a completely different type of attribute. Here is an XML file with attributes in some elements:

<?xml version="1.0" encoding="utf-8" ?>
<videos>
    <video ISBN="0-7888-1623-3">
	<title Screenplay="Marty Kaplan">The Distinguished Gentleman</title>
	<director>Jonathan Lynn</director>
	<length>112 Minutes</length>
	<format>DVD</format>
	<rating>R</rating>
    </video>
    <video>
	<title WrittenBy="Charlie Peter">Her Alibi</title>
	<director>Bruce Beresford</director>
	<length>94 Mins</length>
	<format>DVD</format>
	<rating>PG-13</rating>
    </video>
</videos>

Remember that you can include white spaces to make your code easy to read. This means that you can type an attribute on the next line of its element's name. We know that every element must be closed. We saw that we could close an element with an end-tag as follows:

<video><ISBN>0-7888-1623-3</ISBN></video>

We also saw that we could close an element locally as follows: <video />. If you create an attribute in an empty element, you can also close it by typing the indicative forward slash before the right angle bracket and after an empty space. Here is an example:

<video ISBN="0-7888-1623-3" />

Setting an Attribute by Name and Value

As mentioned already, an attribute primarily belongs to an element. This means that, when creating an attribute, you must specify what element it would belong to. To support the attributes of an element, the XmlElement class is equipped with the SetAttribute() method which is overloaded in two versions. The first version of this method uses the following syntax:

Public Overridable Sub SetAttribute(ByVal name As String, ByVal value As String)

The first argument is the name of the new attribute and the second argument will be its text. Before adding an attribute, you should first identify its parent element. Consider the following file named AutoParts.xml:

<?xml version="1.0" encoding="UTF-8"?>
<auto-parts>
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price>58.85</unit-price>
  </auto-part>
  <auto-part>
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price>44.45</unit-price>
  </auto-part>
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price>14.15</unit-price>
  </auto-part>
</auto-parts>

Here is an example that adds an attribute to the root element:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim xdAutoParts As New XmlDocument()
    Dim strFileName =  Server.MapPath("auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
	    ' Create an attribute and add it to the root element
	    xdAutoParts.DocumentElement.SetAttribute("business", "College Park Auto-Parts")

	    ' Save the file
	    xdAutoParts.Save(fsAutoParts)
	End Using
    End If
%>
</body>
</html>

From the above file, this code would result in:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Shocks, Struts & Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price>58.85</unit-price>
  </auto-part>
  <auto-part>
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price>44.45</unit-price>
  </auto-part>
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price>14.15</unit-price>
  </auto-part>
</auto-parts>

Programmatically Creating an Attribute

To support attribute addition, the XmlDocument class is equipped with the CreateAttribute() method, which is overloaded in three versions. The first version of this method has the following syntax:

Public Function CreateAttribute(ByVal name As String) As XmlAttribute

This method expects the name of the attribute as argument. If it succeeds, this method produces an XmlAttribute object.

Adding Many Attributes to an Element

To let you add a new attribute to an element, the XmlElement class is equipped with a method named SetAttributeNote. This method is overloaded with two versions. One of the versions uses the following syntax:

Public Overridable Function SetAttributeNode(ByVal newAttr As XmlAttribute) As XmlAttribute

This method expects an XmlAttribute object. Here is an example that looks for a particular node in a collection and adds an attribute to it:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim i As Integer
    Dim xnlYears As XmlNodeList
    Dim xaItemNumber As XmlAttribute
    Dim xdAutoParts As New XmlDocument()
    Dim strFileName = Server.MapPath("auto-parts1.xml")

    Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
        xdAutoParts.Load(fsAutoParts)
    End Using

    Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
        ' Create an attribute
        xaItemNumber = xdAutoParts.CreateAttribute("item-number")
        xaItemNumber.Value = "280486"

        ' Get a list of elements whose names are "year"
        xnlYears = xdAutoParts.GetElementsByTagName("year")

        ' Visit each auto part element
        For i = 0 To xnlYears.Count - 1
            ' Look for an auto part that has the year 2015
            If xnlYears(i).InnerText = "2015" Then
                ' Once you find that auto-part, add the new attribute to it
                CType(xnlYears(i).ParentNode, XmlElement).SetAttributeNode(xaItemNumber)

                ' Save the file
                xdAutoParts.Save(fsAutoParts)
            End If
        Next
    End Using
%>
</body>
</html>

From the above file, this code would result in:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price>58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price>44.45</unit-price>
  </auto-part>
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price>14.15</unit-price>
  </auto-part>
</auto-parts>

You might have noticed that the above code made a comparison on the value of only one element, and that type of value (of the year element) is used by more than one element (year = 2012). If you perform the same comparison on a value that is repeated, you would receive an error. Consider the following example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim i As Integer
    Dim xnlYears As XmlNodeList
    Dim xaItemNumber As XmlAttribute
    Dim xdAutoParts As New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)

            ' Create an attribute
            xaItemNumber = xdAutoParts.CreateAttribute("item-number")
            xaItemNumber.Value = "580686"

            ' Get a list of elements whose names are "year"
            xnlYears = xdAutoParts.GetElementsByTagName("year")

            ' Visit each auto part element
            For i = 0 To xnlYears.Count - 1
                ' Look for an auto part that has the year 2015
                If (xnlYears(i).InnerText = "2012") Then
                    ' Once you find that auto-part, add the new attribute to it
                    CType(xnlYears(i).ParentNode, XmlElement).SetAttributeNode(xaItemNumber)
                End If
            Next

            ' Save the file
            xdAutoParts.Save(fsAutoParts)
        End Using
    End If
%>
</body>
</html>

This code would produce an error. An unprofessional solution is to perform the comparison on all or other values of the same element. Here is an example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim i As Integer
    Dim xnlYears As XmlNodeList
    Dim xaItemNumber As XmlAttribute
    Dim xdAutoParts As New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)

            ' Create an attribute
            xaItemNumber = xdAutoParts.CreateAttribute("item-number")
            xaItemNumber.Value = "580686"

            ' Get a list of elements whose names are "year"
            xnlYears = xdAutoParts.GetElementsByTagName("year")

            ' Visit each auto part element
            For i = 0 To xnlYears.Count - 1
                ' Look for an auto part that has the year 2015
                If (xnlYears(i).InnerText = "2012") And
                    (xnlYears(i).NextSibling.InnerText = "Toyota") And
                    (xnlYears(i).NextSibling.NextSibling.InnerText = "Corolla") And
                    (xnlYears(i).NextSibling.NextSibling.NextSibling.InnerText = "Air Filters") And
                    (xnlYears(i).NextSibling.NextSibling.NextSibling.NextSibling.InnerText = "FRAM CF10285 Fresh Breeze Cabin Air Filter") Then
                    ' Once you find that auto-part, add the new attribute to it
                    CType(xnlYears(i).ParentNode, XmlElement).SetAttributeNode(xaItemNumber)
                End If
            Next

            ' Save the file
            xdAutoParts.Save(fsAutoParts)
        End Using
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part>
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Shocks, Struts & Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price>58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price>44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price>14.15</unit-price>
  </auto-part>
</auto-parts>

We referred to this solution as "unprofessional" because there is no guaranty that two elements cannot have the exact same characteristics (same car make, same model, same year, same part name). The better solution used in databases is to give a unique characteristic, sometimes called a unique key, to each record. For our auto-parts application, this would correspond to giving a unique item number to each auto part.

By using the collection of attributes of an element, you can locate an attribute in an element and take an appropriate action, such as adding an attribute to a sibling of the element. Here is an example:

College Park Auto-Parts: auto-parts.xml

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part item-number="937418">
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price>58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price>44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price>14.15</unit-price>
  </auto-part>
</auto-parts>

College Park Auto-Parts: auto-parts.apx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim i As Integer
    Dim xaTrim As XmlAttribute
    Dim xdAutoParts As New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        Dim xnlAutoParts As XmlNodeList = xdAutoParts.GetElementsByTagName("auto-part")

        For i = 0 To xnlAutoParts.Count - 1
            For Each xaPart In xnlAutoParts(i).Attributes
                If (xaPart.Name = "item-number") And (xaPart.Value = "937418") Then
                    ' Create an attribute
                    xaTrim = xdAutoParts.CreateAttribute("trim")
                    xaTrim.Value = "LE"
                    CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaTrim)

                    Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
                        xdAutoParts.Save(fsAutoParts)
                    End Using
                End If
            Next
        Next
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part item-number="937418">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="LE">Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price>58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price>44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model>Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price>14.15</unit-price>
  </auto-part>
</auto-parts>

Adding Many Attributes

In the same, you can create as many attributes as you want. Here are examples:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto Parts</title>
</head>
<body>

<h3>College Park Auto Parts</h3>

<%
    Dim i As Integer
    Dim xaNewPart As XmlAttribute
    Dim xdAutoParts As New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        Dim xnlAutoParts As XmlNodeList = xdAutoParts.GetElementsByTagName("auto-part")

        For i = 0 To xnlAutoParts.Count - 1
            For Each xaPart In xnlAutoParts(i).Attributes
                ' New Attribute
                xaNewPart = xdAutoParts.CreateAttribute("status")
                xaNewPart.Value = "New"
                CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaNewPart)

                If (xaPart.Name = "item-number") And (xaPart.Value = "937418") Then
                    ' New Attribute
                    xaNewPart = xdAutoParts.CreateAttribute("engine")
                    xaNewPart.Value = "1.8L L4"
                    CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaNewPart)

                    ' New Attribute
                    xaNewPart = xdAutoParts.CreateAttribute("body-style")
                    xaNewPart.Value = "4-Speed Automatic Transaxle U341E"
                    CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaNewPart)
                End If

                If (xaPart.Name = "item-number") And (xaPart.Value = "580686") Then
                    ' New Attribute
                    xaNewPart = xdAutoParts.CreateAttribute("trim")
                    xaNewPart.Value = "SE"
                    CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaNewPart)

                    ' New Attribute
                    xaNewPart = xdAutoParts.CreateAttribute("engine")
                    xaNewPart.Value = "2.0L L4 Gas"
                    CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaNewPart)

                    ' New Attribute
                    xaNewPart = xdAutoParts.CreateAttribute("body-style")
                    xaNewPart.Value = "6-Speed Automatic Transaxle 6F"
                    CType(xnlAutoParts(i).FirstChild.NextSibling.NextSibling, XmlElement).SetAttributeNode(xaNewPart)
                End If

                Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
                    xdAutoParts.Save(fsAutoParts)
                End Using
            Next
        Next
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part item-number="937418">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="LE" engine="1.8L L4" body-style="4-Speed Automatic Transaxle U341E">Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price status="New">58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price status="New">44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="SE" engine="2.0L L4 Gas" body-style="6-Speed Automatic Transaxle 6F">Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price status="New">14.15</unit-price>
  </auto-part>
</auto-parts>

Appending an Attribute

Appending an attribute consists of adding an attribute to an element. Imagine the element already has at least one attribute:

<?xml version="1.0" encoding="utf-8"?>
<periodic-table>
  <element>
    <atomic-number>1</atomic-number>
    <name>Hydrogen</name>
    <symbol>H</symbol>
    <atomic-mass>1.0079</atomic-mass>
  </element>
  <element>
    <atomic-number column="18">2</atomic-number>
    <name>Helium</name>
    <symbol>He</symbol>
    <atomic-mass>4.002682</atomic-mass>
  </element>
</periodic-table>

In this case, the new one is positioned to the end of the collection of the attributes of the element. To support this operation, the XmlAttributeCollection class is equipped with a method named Append. Its syntax is:

Public Function Append(ByVal node As XmlAttribute) As XmlAttribute

Here is an example:

chemistry.xml:

<?xml version="1.0" encoding="utf-8"?>
<periodic-table>
  <element>
    <atomic-number>1</atomic-number>
    <name>Hydrogen</name>
    <symbol>H</symbol>
    <atomic-mass>1.0079</atomic-mass>
  </element>
  <element>
    <atomic-number column="18">2</atomic-number>
    <name>Helium</name>
    <symbol>He</symbol>
    <atomic-mass>4.002682</atomic-mass>
  </element>
</periodic-table>

chemistry.aspx:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Chemistry - Periodic Table</title>
</head>
<body>

<h3>Chemistry - Periodic Table</h3>

<%
    Dim xaElement As XmlAttribute
    Dim xnlElements As XmlNodeList
    Dim strFileName = Server.MapPath("App_Data/chemistry.xml")
    Dim xdPeriodicTable As XmlDocument = New XmlDocument()

    If File.Exists(strFileName) Then
        Using fsPeriodicTable As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdPeriodicTable.Load(fsPeriodicTable)
        End Using

        ' New Attribute
        xaElement = xdPeriodicTable.CreateAttribute("row")
        xaElement.Value = "1"
        xnlElements = xdPeriodicTable.GetElementsByTagName("atomic-number")

        For Each xnElement In xnlElements
            If xnElement.InnerText = "2" Then
                xnElement.Attributes.Append(xaElement)

                Using fsPeriodicTable As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
                    ' Save the file
                    xdPeriodicTable.Save(fsPeriodicTable)
                End Using
            End If
        Next
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<periodic-table>
  <element>
    <atomic-number>1</atomic-number>
    <name>Hydrogen</name>
    <symbol>H</symbol>
    <atomic-mass>1.0079</atomic-mass>
  </element>
  <element>
    <atomic-number column="18" row="1">2</atomic-number>
    <name>Helium</name>
    <symbol>He</symbol>
    <atomic-mass>4.002682</atomic-mass>
  </element>
</periodic-table>

If the element doesn't have any attribute(s), the new one is created as the only one.

Prepending an Attribute

Prepending an attribute consists of adding a new attribute to an element. If the element doesn't have any attribute yet, the new attribute is created as the only one. If the element already has at least one attribute, the new one is positioned at the beginning of the collection. To support this operation, the XmlAttributeCollection class is equipped with a method named Prepend. Its syntax is:

Public Function Prepend(ByVal node As XmlAttribute) As XmlAttribute

Here is an example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Chemistry - Periodic Table</title>
</head>
<body>

<h3>Chemistry - Periodic Table</h3>

<%
    Dim xnElement As XmlNode
    Dim xaElement As XmlAttribute
    Dim xnlElements As XmlNodeList
    Dim xdPeriodicTable As XmlDocument = New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/chemistry.xml")

    If File.Exists(strFileName) Then
        Using fsPeriodicTable = New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdPeriodicTable.Load(fsPeriodicTable)
        End Using

        ' New Attribute
        xaElement = xdPeriodicTable.CreateAttribute("column")
        xaElement.Value = "1"
        xnlElements = xdPeriodicTable.GetElementsByTagName("atomic-number")

        For Each xnElement In xnlElements
            If xnElement.InnerText = "1" Then
                xnElement.Attributes.Prepend(xaElement)
            End If
        Next

        Using fsPeriodicTable As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
            xdPeriodicTable.Save(fsPeriodicTable)
        End Using
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<periodic-table>
  <element>
    <atomic-number column="1" row="1">1</atomic-number>
    <name>Hydrogen</name>
    <symbol>H</symbol>
    <atomic-mass>1.0079</atomic-mass>
  </element>
  <element>
    <atomic-number column="18" row="1">2</atomic-number>
    <name>Helium</name>
    <symbol>He</symbol>
    <atomic-mass>4.002682</atomic-mass>
  </element>
</periodic-table>

Inserting an Attribute

To create a new attribute before it, you can call the XmlAttributeCollection.InsertBefore() method. Its syntax is:

Public Function InsertBefore(ByVal newNode As XmlAttribute,
			     ByVal refNode As XmlAttribute) As XmlAttribute

To add a new attribute after the current one, you can call the XmlAttributeCollection.InsertAfter() method. Its syntax is:

Public Function InsertAfter(ByVal newNode As XmlAttribute,
			    ByVal refNode As XmlAttribute) As XmlAttribute

The Parent of an Attribute

Once an attribute has been created, to identify the element to which it belongs, you can access its XmlAttribute.OwnerElement property. This property produces an XmlElement value:

Public Overridable ReadOnly Property OwnerElement As XmlElement

Editing/Updating an Attribute

Editing or updating an attribute consists of changing something about it, such as its value. You have many options.

To edit or update an attribute, you can start by locating it. This time too, you have many options. The classic way is to use a series of loops to navige both the elements and their attributes to locate the particular attribute you want. Here is an example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto-Parts - Part Update</title>
</head>
<body>

<h3>College Park Auto-Parts - Part Update</h3>

<%
    Dim i As Integer
    Dim xdAutoParts As New XmlDocument()
    Dim xnlAutoParts, xnlUnitPrices As XmlNodeList
    Dim strFileName = Server.MapPath("App_Data/auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        xnlAutoParts = xdAutoParts.GetElementsByTagName("auto-part")

        For i = 0 To xnlAutoParts.Count - 1
            For Each xaPart In xnlAutoParts(i).Attributes
                If (xaPart.Name = "item-number") And (xaPart.Value = "280486") Then
                    xnlUnitPrices = xnlAutoParts(i).ChildNodes

                    For Each xnUnitPrice In xnlUnitPrices
                        If xnUnitPrice.Name = "unit-price" Then
                            For Each xaStatus In xnUnitPrice.Attributes
                                If xaStatus.Name = "status" Then
                                    . . .
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        Next
    End If
%>
</body>
</html>

After accessing the attribute, you can manipulate it as you see fit. For example, you can change its value. Here is an example:

College Park Auto-Parts: auto-parts.xml

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part item-number="937418">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="LE" engine="1.8L L4" body-style="4-Speed Automatic Transaxle U341E">Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price status="New">58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-pricestatus="New">44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="SE" engine="2.0L L4 Gas" body-style="6-Speed Automatic Transaxle 6F">Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price status="New">14.15</unit-price>
  </auto-part>
</auto-parts>

College Park Auto-Parts: edit-part.aspx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>College Park Auto-Parts - Part Update</title>
</head>
<body>

<h3>College Park Auto-Parts - Part Update</h3>

<%
    Dim i As Integer
    Dim xdAutoParts As New XmlDocument()
    Dim xnlAutoParts, xnlUnitPrices As XmlNodeList
    Dim strFileName = Server.MapPath("App_Data/auto-parts.xml")

    If File.Exists(strFileName) Then
        Using fsAutoParts As New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdAutoParts.Load(fsAutoParts)
        End Using

        xnlAutoParts = xdAutoParts.GetElementsByTagName("auto-part")

        For i = 0 To xnlAutoParts.Count - 1
            For Each xaPart In xnlAutoParts(i).Attributes
                If (xaPart.Name = "item-number") And (xaPart.Value = "280486") Then
                    xnlUnitPrices = xnlAutoParts(i).ChildNodes

                    For Each xnUnitPrice In xnlUnitPrices
                        If xnUnitPrice.Name = "unit-price" Then
                            For Each xaStatus In xnUnitPrice.Attributes
                                If xaStatus.Name = "status" Then
                                    xaStatus.InnerText = "Refurbished"
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        Next

        Using fsAutoParts As New FileStream(strFileName, FileMode.Create, FileAccess.Write)
            xdAutoParts.Save(fsAutoParts)
        End Using
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<auto-parts business="College Park Auto-Parts">
  <auto-part item-number="937418">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="LE" engine="1.8L L4" body-style="4-Speed Automatic Transaxle U341E">Corolla</model>
    <category>Shocks, Struts &amp; Suspension</category>
    <part-name>KYB SM5215 Strut mount</part-name>
    <unit-price status="New">58.85</unit-price>
  </auto-part>
  <auto-part item-number="280486">
    <year>2015</year>
    <make>Ford</make>
    <model>Escape</model>
    <category>Brake System</category>
    <part-name>Power Stop (16-1044) Z16 Ceramic Brake Pad</part-name>
    <unit-price status="Refurbished">44.45</unit-price>
  </auto-part>
  <auto-part item-number="580686">
    <year>2012</year>
    <make>Toyota</make>
    <model trim="SE" engine="2.0L L4 Gas" body-style="6-Speed Automatic Transaxle 6F">Corolla</model>
    <category>Air Filters</category>
    <part-name>FRAM CF10285 Fresh Breeze Cabin Air Filter</part-name>
    <unit-price status="New">14.15</unit-price>
  </auto-part>
</auto-parts>

Removing Attributes

Deleting an Attribute by its Name

If an element has an attribute you don't want or that you don't need anymore, you can delete that attribute. You have various options, two are available through the XmlElement class.

Using the XmlElement.RemoveAttributeAt() method to delete an attribute can be uncertain because you would not know whether there is an attribute at the specified position. An alternative is to specify the name of the attribute you want to delete. To support this, the XmlElement class is equipped with the RemoveAttribute() method, which is overloaded with two versions. One of the versions of this method uses the following syntax:

Public Overridable Sub RemoveAttribute(ByVal name As String)

This method expects as argument the name of the attribute to remove. Consider the following file named TimeZones.xml:

<?xml version="1.0" encoding="utf-8" ?>
<time-zones>
  <zone>
    <name initials="CST">Central Standard Time</name>
    <utc>-06:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="West South Central" bea-region="Southeast">Arkansas</state>
      <state inclusion="Split" cb-region="South Atlantic" bea-region="Southeast">Florida</state>
      <state inclusion="Entirely" cb-region="West North Central" bea-region="Plains">Minnesota</state>
      <state inclusion="Entirely" cb-region="East North Central" bea-region="Great Lakes">Ohio</state>
    </states-and-territories>
  </zone>
  <zone>
    <name initials="EST">Eastern Standard Time</name>
    <utc>-05:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Maine</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Vermont</state>
      <state inclusion="Split" cb-region="South Atlantic" bea-region="Southeast">Florida</state>
    </states-and-territories>
  </zone>
</time-zones>

Here is an example of calling this method:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Chemistry - Periodic Table</title>
</head>
<body>

<h3>Chemistry - Periodic Table</h3>

<%
    Dim xnTimeZone As XmlNode
    Dim xnlTimeZones, xnlStates As XmlNodeList
    Dim xdTimeZones As XmlDocument = New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/TimeZones.xml")

    If File.Exists(strFileName) Then
        Using fsTimeZones = New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdTimeZones.Load(fsTimeZones)
        End Using

        ' Get a list of elements whose names are "name"
        xnlTimeZones = xdTimeZones.GetElementsByTagName("name")

        Try
            ' Visit each time zone element
            For Each xnTimeZone In xnlTimeZones
                ' Look for a time zone named Eastern Standard Time
                If xnTimeZone.InnerText = "Eastern Standard Time" Then
                    ' Get a list of the third siblings of that node. This represents the states
                    xnlStates = xnTimeZone.NextSibling.NextSibling.ChildNodes

                    ' Visit each state
                    For Each xnState In xnlStates
                        ' Look for a state named Florida
                        If xnState.InnerText = "Florida" Then
                            ' Get its attributes
                            For Each xaCharacteristics In xnState.Attributes
                                If xaCharacteristics.Name = "cb-region" Then
                                    CType(xnState, XmlElement).RemoveAttribute("cb-region")

                                    Using fsTimeZones = New FileStream(strFileName, FileMode.Create, FileAccess.Write)
                                        xdTimeZones.Save(fsTimeZones)
                                    End Using
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        Catch ioe As InvalidOperationException
        End Try
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<time-zones>
  <zone>
    <name initials="CST">Central Standard Time</name>
    <utc>-06:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="West South Central" bea-region="Southeast">Arkansas</state>
      <state inclusion="Split" cb-region="South Atlantic" bea-region="Southeast">Florida</state>
      <state inclusion="Entirely" cb-region="West North Central" bea-region="Plains">Minnesota</state>
      <state inclusion="Entirely" cb-region="East North Central" bea-region="Great Lakes">Ohio</state>
    </states-and-territories>
  </zone>
  <zone>
    <name initials="EST">Eastern Standard Time</name>
    <utc>-05:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Maine</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Vermont</state>
      <state inclusion="Split" bea-region="Southeast">Florida</state>
    </states-and-territories>
  </zone>
</time-zones>

Removing an Attribute by Position

The attributes of an XmlElement object are considered stored in an indexed list with the most left attribute at index 0, the second from left at index 1, and so on. Based on this, to remove an attribute by locating it based on its index, you can call the XmlElement.RemoveAttributeAt() method. Its syntax is:

Public Overridable Function RemoveAttributeAt(ByVal i As Integer) As XmlNode

When calling this method, if an attribute exists at position i, it will be deleted and the method would return it. If there is no attribute at that index, the method doesn't do anything and it returns 0.

Using the list of attributes of an element, you can delete one or all attributes of an element. Since the attributes are stored in a collection, you can locate the undesired attribute by its index and then delete it. To do this, you can call the XmlAttributeCollection.RemoveAt() method. Its syntax is:

Public Function RemoveAt(ByVal i As Integer) As XmlAttribute

This method expects the index of the attribute that needs to be removed. As mentioned for the XmlAttributeCollection.ItemOf indexed property, to efficiently use this RemoveAt() method, you should know the exact index of the attribute, otherwise, you may access and therefore delete the wrong attribute. Here is an example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Time Zones</title>
</head>
<body>

<h3>Time Zones</h3>

<%
    Dim i As Integer
    Dim xnTimeZone, xnState As XmlNode
    Dim xnlTimeZones, xnlStates As XmlNodeList
    Dim xdTimeZones As XmlDocument = New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/TimeZones.xml")


    If File.Exists(strFileName) Then
        Using fsTimeZones = New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdTimeZones.Load(fsTimeZones)
        End Using

        ' Get a list of elements whose names are "name"
        xnlTimeZones = xdTimeZones.GetElementsByTagName("name")

        Try
            ' Visit each time zone element
            For Each xnTimeZone In xnlTimeZones
                ' Look for a time zone named Eastern Standard Time
                If xnTimeZone.InnerText = "Eastern Standard Time" Then
                    ' Get a list of the third siblings of that node. This represents the states
                    xnlStates = xnTimeZone.NextSibling.NextSibling.ChildNodes

                    ' Visit each state
                    For Each xnState In xnlStates
                        ' Look for a state named Maine
                        If xnState.InnerText = "Maine" Then
                            ' Get its attributes
                            For i = 0 To xnState.Attributes.Count - 1
                                If xnState.Attributes(i).Name = "bea-region" Then
                                    CType(xnState, XmlElement).RemoveAttributeAt(i)

                                    Using fsTimeZones = New FileStream(strFileName, FileMode.Create, FileAccess.Write)
                                        xdTimeZones.Save(fsTimeZones)
                                    End Using
                                End If
                            Next
                        End If
                    Next
                End If
            Next
        Catch ioe As InvalidOperationException
        End Try

    End If
%>
</body>
</html>

Removing an Attribute Based on its Name

Another technique you can use consists of defining an XmlAttribute object and submitting to its XmlElement parent to delete. To do this, you can call the RemoveAttributeNode() method of the XmlElement object. Its syntax is:

Public Overridable Function RemoveAttributeNode(ByVal oldAttr As XmlAttribute) As XmlAttribute

When calling this method, pass the attribute object as argument. If the attribute exists, it would be removed and the method would return the deleted attribute. If the attribute doesn't exist, nothing would happen. Here is an example:

An alternative is to explicitly identify the attribute you want to delete. To do this, you can call the XmlAttributeCollection.Remove() method. Its syntax is:

Public Function Remove(ByVal node As XmlAttribute) As XmlAttribute

This method takes as attribute the XmlAttribute identification of the attribute you want to remove.

Clearing an Element of Attributes

To delete all attributes of an element, you can call the XmlAttributeCollection.RemoveAll() method. Its syntax is:

Public Sub RemoveAll

This method would simply remove all attributes that belong to an XmlElement object. Here is an example:

<%@ Page Language="VB" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Xml" %>

<!DOCTYPE html>

<html>
<head runat="server">
<title>Time Zones</title>
</head>
<body>

<h3>Time Zones</h3>

<%
    Dim i As Integer
    Dim xnTimeZone, xnState As XmlNode
    Dim xnlTimeZones, xnlStates As XmlNodeList
    Dim xdTimeZones As XmlDocument = New XmlDocument()
    Dim strFileName = Server.MapPath("App_Data/TimeZones.xml")

    If File.Exists(strFileName) Then
        Using fsTimeZones = New FileStream(strFileName, FileMode.Open, FileAccess.Read)
            xdTimeZones.Load(fsTimeZones)
        End Using

        ' Get a list of elements whose names are "name"
        xnlTimeZones = xdTimeZones.GetElementsByTagName("name")

        ' Visit each time zone element
        For Each xnTimeZone In xnlTimeZones
            ' Look for a time zone named Eastern Standard Time
            If xnTimeZone.InnerText = "Eastern Standard Time" Then
                ' Get a list of the third siblings of that node. This represents the states
                xnlStates = xnTimeZone.NextSibling.NextSibling.ChildNodes

                ' Visit each state
                For Each xnState In xnlStates
                    ' Look for a state named Florida
                    If xnState.InnerText = "Florida" Then
                        xnState.Attributes.RemoveAll()

                        Using fsTimeZones = New FileStream(strFileName, FileMode.Create, FileAccess.Write)
                            xdTimeZones.Save(fsTimeZones)
                        End Using
                    End If
                Next
            End If
        Next
    End If
%>
</body>
</html>

This would produce:

<?xml version="1.0" encoding="utf-8"?>
<time-zones>
  <zone>
    <name initials="CST">Central Standard Time</name>
    <utc>-06:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="West South Central" bea-region="Southeast">Arkansas</state>
      <state inclusion="Split" cb-region="South Atlantic" bea-region="Southeast">Florida</state>
      <state inclusion="Entirely" cb-region="West North Central" bea-region="Plains">Minnesota</state>
      <state inclusion="Entirely" cb-region="East North Central" bea-region="Great Lakes">Ohio</state>
    </states-and-territories>
  </zone>
  <zone>
    <name initials="EST">Eastern Standard Time</name>
    <utc>-05:00</utc>
    <states-and-territories>
      <state inclusion="Split" cb-region="East South Central" bea-region="Southeast">Alabama</state>
      <state inclusion="Entirely" cb-region="New England">Maine</state>
      <state inclusion="Entirely" cb-region="New England" bea-region="New England">Vermont</state>
      <state>Florida</state>
    </states-and-territories>
  </zone>
</time-zones>

Previous Copyright © 2009-2016, FunctionX Next