When studying XML elements we saw how they constitute the
main objects of an XML document. We also saw that an element can be nested
inside of another element. Instead of nesting an element, you can transform the
nested element into being part of 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:

Both (must) have a name

Each may or may not have a value

The differences between an element and an attribute are:

An attribute is considered a characteristic of an element. This means that
an attribute belongs to an element

An element can have one or more attributes. As mentioned already, an
attribute cannot have an element

An attribute must be created in the start-tag of an element

An element cannot be defined as part of an attribute

Practical Learning: Introducing Attributes

Start a new Windows Application named Countries1

To add an XML file, on the main menu, click File -> New -> File...

In the Templates list of the New File dialog box, click XML File (.xml)
and click Open

To save the file, on the the Standard toolbar, click the Save button

Locate the folder of the current project and double-click its bin sub-folder
to display it in the Save
In combo box

Change the file name to Countries and click Save

The Name and Value of an Attribute

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, the name of the
attribute, and assign it a value as a string. Imagine you have an ISBN element
as a child of a Video element as follows:

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

In this case, since ISBN is simply a child of the Video
element, you can change the ISBN element to become an attribute of the Video
element as follows:

<Video ISBN="0-7888-1623-3">

Now, ISBN is an attribute of the Video element.

An attribute mostly gets meaning because of its text. This
text allows you to know what the attribute is holding at one particular time.
One of three properties can be used to specify or to retrieve the text held by
an attribute. The XmlAttribute.Value is the most commonly used property
to get or set this information. Besides Value, you can also use XmlAttribute.InnerText
or XmlAttribute.InnerXml to access the text of an attribute.

An Element With a Single Attribute

Introduction

An element can have 0, one, or more attributes. The attributes of an element are stored
in the XmlElement.Attributes property and held by 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 XmlElement.HasAttributes
property. 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:

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 name. In the previous lesson, we saw that every element must be
closed. We saw that you can close an element with an end-tag as follows:

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

We also saw that you can 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" />

To support attributes, the System.Xml namespace
provides the XmlAttribute class which is derived from XmlNode. One
of the two most important properties of an attribute is its name, represented by
Name. Every attribute must have a name, which is used to identify the
attribute. For one thing, you must be able to locate an attribute in an element,
for another, if an element has many attributes, you need to be able to identify
one of them by name.

Practical Learning: Creating Simple Attributes

To create simple attributes, change the Countries.xml file as follows:

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 has the following syntax:

Overloads 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. Here is an example that adds an attribute to the
root element:

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:

Overloads Public Function CreateAttribute(ByVal name As String) As XmlAttribute

This method expects the name of the attribute as argument.
If it succeeds, it produces an XmlAttribute object. To add the
new attribute to an element, you can call the XmlElement.SetAttributeNote()
method. This method is overloaded in two versions. One of the versions (the
first) uses the following syntax:

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

This method expects an XmlAttribute as a constant pointer.

Practical Learning: Creating an Attribute

To add a new form, on the main menu, click Project -> Add Windows
Form...

In the Templates list of the Add New Item dialog box, make sure Windows Form
is selected
Set the Name to NewContinent and click Open

To add a new form, on the main menu, click Project -> Add Windows
Form...

In the Templates list of the Add New Item dialog box, make sure Windows Form
is selected
Set the Name to NewCountry and click Open

Add a new Button to the form and set its Properties as follows:Name: btnNewContinent
Text: New Continent

Double-click the New Continent button

In the top section of the file, above the Public Class NewCountry line,
type

Imports System.Xml

Implement its Click event as follows:

Private Sub btnNewContinent_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewContinent.Click
Dim frmContinent As New NewContinent
' Open the XML file
Dim xmlDocContinents As New XmlDocument
xmlDocContinents.Load("Countries.xml")
' Display the New Continent dialog box and find out if the user clicked OK
If frmContinent.ShowDialog() = DialogResult.OK Then
If frmContinent.txtContinentName.Text = "" Then
Exit Sub
End If
' Create an element that the new attribute will be added to
Dim xmlNewContinent As XmlElement = xmlDocContinents.CreateElement("Continent")
' Create a Continent element and set its value to
' that of the New Continent dialog box
xmlNewContinent.SetAttribute("Name", frmContinent.txtContinentName.Text)
' Add the element and its attribute to the document
xmlDocContinents.DocumentElement.AppendChild(xmlNewContinent)
' Save the XML file
xmlDocContinents.Save("Countries.xml")
End If
End Sub

Display the first or main form (Form1.vb [Design]) and add a new Button
control to it

Set its Name to btnNewCountry and its Text to New Country

Double-click the New Country button and implement its Click event as follows:

Private Sub btnNewContinent_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewContinent.Click
Dim frmContinent As New NewContinent
' Open the XML file
Dim xmlDocContinents As New XmlDocument
xmlDocContinents.Load("Countries.xml")
' Display the New Continent dialog box and find out if the user clicked OK
If frmContinent.ShowDialog() = DialogResult.OK Then
If frmContinent.txtContinentName.Text = "" Then
Exit Sub
End If
' Create an element that the new attribute will be added to
Dim xmlNewContinent As XmlElement = xmlDocContinents.CreateElement("Continent")
' Create a Continent element and set its value to
' that of the New Continent dialog box
xmlNewContinent.SetAttribute("Name", frmContinent.txtContinentName.Text)
' Add the element and its attribute to the document
xmlDocContinents.DocumentElement.AppendChild(xmlNewContinent)
' Save the XML file
xmlDocContinents.Save("Countries.xml")
End If
End Sub

Execute the application and test it by creating a new continent whose name
is North America

Close the form and return to your programming environment

The Parent of an Attribute

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

Attribute Removal

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.

The attributes of an XmlElement are considered stored in an
indexed list (in the next sections, we will see that the attributes are stored
in a collection) 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 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 (the first) of this method uses the following
syntax:

Overloads Public Overridable Sub RemoveAttribute(ByVal name As String)

This method accepts as argument the name of the attribute to
remove.

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

Overloads 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.

Practical Learning: Removing Attributes

Access the NewCountry.vb file and change the code of the
btnNewContinent Click event as follows:

Private Sub btnNewContinent_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNewContinent.Click
' Open the XML file
Dim xmlDocContinents As New XmlDocument
xmlDocContinents.Load("Countries.xml")
' Since we are planning to create new elements and their attributes
' delete all continents
Dim elmRoot As XmlElement = xmlDocContinents.DocumentElement
elmRoot.RemoveAll()
' Save the XML file
xmlDocContinents.Save("Countries.xml")
End Sub