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

While an element can have one or more attributes, an attribute can
neither have an element nor have another or more attributes

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

An element cannot be defined as part of an attribute. That is, an
attribute is subject to an element and an attribute doesn't own the
attribute

Creating an Attribute

Imagine you have an ISBN element as a child of a Video
element as follows:

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

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

Operations on an XML Attribute

The Inner Text of an Attribute

In the .NET Framework, an attribute is represented by
the XmlAttribute class. Like all nodes, this class is based on the
XmlNode class. The name of an attribute is represented by its
(read-only) Name property. The value of an attribute is represented
by its Value property. Besides Value, you can also use
XmlAttribute.InnerText or XmlAttribute.InnerXml to access the
text of an attribute.

Creating an Attribute

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:

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. In
Lesson 7, we
saw 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 on an Element

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 virtual void SetAttribute(string name, string value);

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:

public XmlAttribute CreateAttribute(string name);

This method expects the name of the attribute as
argument. If it succeeds, this method 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 uses the following syntax:

public virtual XmlAttribute SetAttributeNode(XmlAttribute newAttr);

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

private void btnDocument_Click(object sender, EventArgs e)
{
string strFilename = "videos.xml";
XmlDocument docXML = new XmlDocument();
if (File.Exists(strFilename))
{
// Open the XML file
docXML.Load(strFilename);
// Create a new attribute
XmlAttribute atrXML = docXML.CreateAttribute("ISBN");
atrXML.Value = "0-7907-3900-3";
// Get a list of elements whose names are Video
XmlNodeList nodVideos = docXML.GetElementsByTagName("video");
// Since we will look for a specific video, get the list of all titles
XmlNodeList nodTitles = docXML.GetElementsByTagName("title");
// Visit each title
for (int i = 0; i < nodTitles.Count; i++)
{
// Look for a video whose title is "Her Alibi"
if (nodTitles[i].InnerText.Equals("Her Alibi"))
{
// Once you find that video, add the new attribute to it
((XmlElement)(nodVideos[i])).SetAttributeNode(atrXML);
}
}
docXML.Save("videos.xml");
}
}

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 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 virtual XmlNode RemoveAttributeAt(int i);

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 of this
method uses the following syntax:

public virtual void RemoveAttribute(string name);

This method expects 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 call the RemoveAttributeNode() method of
the XmlElement object. Its syntax is:

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.

The Collection of Attributes of an Element

Introduction

So far, we have used only one attribute per element.
Fortunately, you can create as many attributes as you judge necessary in an
element. To do this, type the name of each attribute, assign it a
double-quoted string and separate the attribute from the next with an empty
space. Here is an example of an element with different attributes:

As mentioned already and as you should always remember,
attributes belong to an element. To support them, the attributes of an
element are stored in the Attributes property of the XmlElement
class. The XmlElement.Attributes property is based on a class called
XmlAttributeCollection.

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

Attribute Addition

Whether using its index or name, after accessing an
attribute, you can manipulate it as you see fit. For example, you can change
or delete it using the same techniques we saw to perform on an individual
attribute.

As mentioned already, the attributes are stored as a
list. Because you have complete access to this list and the positions of its
attributes, when creating or adding a new attribute, you can specify the
position the new attribute should have in the collection. To create an
attribute as the first in an element, you can call the
XmlAttributeCollection.Prepend() method. Its syntax is:

public virtual XmlAttribute Prepend(XmlAttribute node);

Another technique you can use consists of locating an
attribute first. Once you have one, to create a new attribute before it, you
can call the XmlAttributeCollection.InsertBefore() method. Its syntax
is:

To add an attribute at the end of the list of attributes
of an element, you can call the XmlAttributeCollection.Append()
method. Its syntax is:

public virtual XmlAttribute Append(XmlAttribute node);

Access to an XML Attribute

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

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 virtual XmlAttribute this[int i] {get;}

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:

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 item to use the index
to locate an attribute. Fortunately, the second version of the overloaded
XmlAttributeCollection.ItemOf[] property has the following syntax:

public virtual XmlAttribute this[string name] {get;}

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

Attribute Removal

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 virtual XmlAttribute RemoveAt(int i);

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. 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 virtual XmlAttribute Remove(XmlAttribute node);

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

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

public virtual void RemoveAll();

This method would simply remove all attributes that
belong to an XmlElement object.

Overview of Types of Nodes

Introduction

To differentiate the various nodes that belong to an XML
file, they are classified by their category. As mentioned earlier, the types
of node are listed in the XmlNodeType enumerator.

Comments

A comment is a character, a line or a paragraph that is
not considered as part of the XML code that needs to be processed. A comment
allows you to insert notes or personal observations inside an XML file. For
this reason, a commented section can be written any way you like. This means
that a comment can include plain text, formulas, expressions, or even XML
code as long as you know that that XML code will not be validated: it will
ignored by the parser.

To create a comment, you use the following formula:

<!-- Blah Blah Blah ->

Between <!-- and -->, any text in that section is
considered a comment and you can include anything you want. Both sections of
the comment use two dashes, not more, not less. Here is an example:

The System.Xml represents a comment through the
XmlComment class. Like any other part of an XML file, a comment is
represented by the XmlComment.Name property. This allows you to
retrieve the name of a comment that is included in the document.

To create a comment, you can call the
XmlDocument.CreateComment() method. Its syntax is:

public virtual XmlComment CreateComment(string data);

This method takes as argument the text that would go
into the commented section. After calling it, if the method succeeds, which
it usually does, it returns the XmlComment object that was created.

CDATA

Except for comments, the parser is used to "scan" the
whole XML file to analyze it. Every tag is then interpreted. As we mentioned
already, the value of each tag can be displayed in a browser between its
opening and its closing tag, and the browser uses different font styles to
make a distinction. When creating some tags and some sections of the file,
you may want the parser to consider those particular tags and sections as
regular text. That is, you may want the parser to treat a certain tag and
its value as if it were regular text even though it is created as an XML
file.

To prevent the parser from interpreting a tag regularly
but to treat that tag and its value as regular text, you can create it in a
CDATA section. To do this, create a section that starts with
<![CDATA[, followed by anything you want, and ending with ]]>.
The formula used is:

<![CDATA[ Blah Blah Blah ]]>

Between <![CDATA[ and ]]>, you can type
anything, including one or more normal XML tags. Here is an example:

The .NET Framework
supports the creation of a CDATA section through the
XmlCDataSection class. This class is equipped with a Name property that
allows you t retrieve the name of a CDATA section in an
XmlDocument object.

To programmatically create a CDATA section, you
can call the XmlDocument.CreateCDataSection() method. Its syntax is:

public virtual XmlCDataSection CreateCDataSection(string data);

This method receives the content of the CDATA
section as argument. If the method succeeds, which it usually does, it
returns an XmlCDataSection value.