Home

The Attributes of an 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 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 does not own the attribute

Practical Learning: Introducing XML Attributes

  1. Start Microsoft Visual Basic and create a Windows Application named AltairRealtors1
  2. To create a new form, on the main menu, click Projects -> Add Windows Form...
  3. Set the Name to PropertyEditor and click Add
  4. Design the form as follows:
     
    Altair Realtors: Property Editor
    Control Text Name Other Properties
    Label Label Property Code:    
    TextBox TextBox   txtPropertyCode Modifiers: Public
    Label Label Status    
    ComboBox ComboBox   cbxStatus Modifiers: Public
    Items:
    Sold
    Available
    Needs Repair
    Label Label      
    DateTimePicker   dtpDateListed Modifiers: Public
    Format: Short
    Label Label Year Built:    
    TextBox TextBox   txtYearBuilt  
    Label Label Property Type:    
    ComboBox ComboBox   cbxPropertyTypes Modifiers: Public
    Items:
    Unknown
    Single Family
    Townhouse
    Condominium
    Label Label Style:    
    ComboBox ComboBox   cbxStyles Modifiers: Public
    Items:
    Farm
    Colonial
    Victorian
    Contemporary
    Label Label Address:    
    TextBox TextBox   txtAddress Modifiers: Public
    Label Label City:    
    TextBox TextBox   txtCity Modifiers: Public
    Label Label Location:    
    TextBox TextBox   txtLocation Modifiers: Public
    Label Label State:    
    ComboBox ComboBox   cbxStates Modifiers: Public
    Items:
    DC
    MD
    PA
    VA
    WV
    Label Label ZIP Code:    
    TextBox TextBox   txtZIPCode Modifiers: Public
    Label Label Stories    
    TextBox TextBox 0 txtStories Modifiers: Public
    Label Label Bedrooms:    
    TextBox TextBox 0 txtBedrooms Modifiers: Public
    Label Label Bathrooms:    
    TextBox TextBox 0.0 txtBathrooms Modifiers: Public
    Label Label Condition:    
    ComboBox ComboBox   cbxConditions Modifiers: Public
    Items:
    Good
    Excellent
    Needs Repairs
    Label Label Market Value:    
    TextBox TextBox 0.00 txtMarketValue Modifiers: Public
    Label Label Picture Path:    
    TextBox TextBox   txtPicturePath Modifiers: Public
    Enabled: False
    Button Button Select Picture... btnPicture  
    PictureBox   pbxProperty Modifiers: Public
    SizeMode: Zoom
    Button Button OK btnOK DialogResult: OK
    Button Button Cancel btnCancel DialogResult: Cancel
    OpenFileDialog (Name): dlgPicture
    Title: Select Property Picture
    DefaultExt: jpg
    Filter: JPEG Files (*.jpg,*.jpeg)|*.jpg|GIF Files (*.gif)|*.gif|Bitmap Files (*.bmp)|*.bmp|PNG Files (*.png)|*.png
    Form
    FormBorderStyle: FixedDialog
    Text: Altair Realtors - Property Editor
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  5. Double-click the Select Picture button and implement its event as follows:
     
    Private Sub btnPicture_Click(ByVal sender As System.Object, _
                                     ByVal e As System.EventArgs) _
                                     Handles btnPicture.Click
            If dlgPicture.ShowDialog() = DialogResult.OK Then
                txtPicturePath.Text = dlgPicture.FileName
                pbxProperty.Image = Image.FromFile(txtPicturePath.Text)
            End If
    End Sub
  6. In the Solution Explorer, right-click Form1.vb and click Rename
  7. Type RealEstate.vb and press Enter twice (to display that form)
  8. From the Toolbox, add a ListView to the form
  9. While the new list view is still selected, in the Properties window, click the ellipsis button of the Columns field and create the columns as follows:
     
    (Name) Text TextAlign Width
    colIndex #   40
    colPropertyCode Prop Code Center 65
    colPropertyType Property Type   80
    colPropertyCondition Condition   65
    colLocation Location   70
    colStories Stories Right 45
    colBedrooms Bedrooms Right 62
    colBathrooms Bathrooms Right 62
    colMarketValue Market Value Right 75
  10. Design the form as follows: 
     
     
    Control Text Name Other Properties
    ListView   lvwAllocations View: Details
    GridLines: True
    FullRowSelect: True
    Anchor: Top, Bottom, Left, Right
    PictureBox   pbxProperty Anchor: Bottom, Left
    Label Description   Anchor: Bottom, Right
    TextBox   txtDescription Multiline: True
    Anchor: Bottom, Right
    Button New Property... btnNewProperty Anchor: Bottom, Right
    Button Close btnClose Anchor: Bottom, Right
  11. Right-click the form and click View Code
  12. Above the Public Class line, add the following lines
     
    Imports System.IO
    Imports System.Xml
    
    Public Class RealEstate
    
    End Class
  13. In the Class Name combo box, select btnNewProperty
  14. In the Method Name combo box, select Click and implement the event as follows:
     
    Imports System.IO
    Imports System.Xml
    
    Public Class RealEstate
    
        Private Sub btnNewProperty_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewProperty.Click
            ' Get a reference to the property editor
            Dim Editor As PropertyEditor = New PropertyEditor
            Dim Filename As String = "properties.xml"
    
            If Editor.ShowDialog() = DialogResult.OK Then
                Dim PropertyType As String, Location As String
                Dim Stories As Integer, Bedrooms As Integer
                Dim Bathrooms As Single
                Dim MarketValue As Double
    
                ' We will need a reference to the XML document
                Dim DOMProperties As XmlDocument = New XmlDocument
    
                ' Find out if the file exists already
                ' If it doesn't, then create it
                If Not File.Exists(Filename) Then
                    DOMProperties.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" & _
                                          "<Listing></Listing>")
                    DOMProperties.Save(Filename)
                End If
    
                ' Open the XML file
                DOMProperties.Load(Filename)
    
                ' Get a reference to the root node
                Dim RootElement As XmlElement = DOMProperties.DocumentElement
    
                PropertyType = Editor.cbxPropertyTypes.Text
                Location = Editor.txtLocation.Text
                Stories = CInt(Editor.txtStories.Text)
                Bedrooms = CInt(Editor.txtBedrooms.Text)
                Bathrooms = CSng(Editor.txtBathrooms.Text)
                MarketValue = CDbl(Editor.txtMarketValue.Text)
    
                ' Create a node named Property
                Dim PropertyElement As XmlElement = DOMProperties.CreateElement("Property")
                ' Add it to the root element
                RootElement.AppendChild(PropertyElement)
    
                ' Create a node named PropertyType
                PropertyElement = DOMProperties.CreateElement("PropertyType")
                Dim TextProperty As XmlText = DOMProperties.CreateTextNode(PropertyType)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Location
                PropertyElement = DOMProperties.CreateElement("Location")
                TextProperty = DOMProperties.CreateTextNode(Location)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Stories
                PropertyElement = DOMProperties.CreateElement("Stories")
                TextProperty = DOMProperties.CreateTextNode(Stories.ToString())
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Bedrooms
                PropertyElement = DOMProperties.CreateElement("Bedrooms")
                TextProperty = DOMProperties.CreateTextNode(Bedrooms.ToString())
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Bathrooms
                PropertyElement = DOMProperties.CreateElement("Bathrooms")
                TextProperty = DOMProperties.CreateTextNode(Bathrooms.ToString("F"))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named MarketValue
                PropertyElement = DOMProperties.CreateElement("MarketValue")
                TextProperty = DOMProperties.CreateTextNode(MarketValue.ToString("F"))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Save the XML file
                DOMProperties.Save(Filename)
            End If
        End Sub
    End Class
  15. Execute the application
  16. Click the New Property button
  17. Enter the following pieces of information:
     
    Property Type Single Family
    Location White Oak
    Stories 2
    Bedrooms 3
    Bathrooms 2.5
    Market Value 465580
  18. Click OK
  19. Close the form and return to your programming environment
  20. From the main menu of Visual Studio, open the properties.xml file from the AltairRealtors1\AltairRealtors\bin\Debug folder: 

    <?xml version="1.0" encoding="utf-8"?>
    <Listing>
      <Property>
        <PropertyType>Single Family</PropertyType>
        <Location>White Oak</Location>
        <Stories>2</Stories>
        <Bedrooms>3</Bedrooms>
        <Bathrooms>2.50</Bathrooms>
        <MarketValue>365580.00</MarketValue>
      </Property>
    </Listing>
  21. Display the RealEstate.vb file

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 and Inner XML 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 the XmlAttribute.InnerText or the XmlAttribute.InnerXml properties to access the text of an attribute.

Programmatically 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 HasAttributes Boolean property of its XmlElement element. If this property produces a True value, then the element has at least one attribute. Otherwise, the element does not have any attribute.

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. 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 Overridable Sub SetAttribute(name As String, 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:

Imports System.Xml
Imports System.IO

Public Class Exercise

    Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
        Dim Filename As String = "videos.xml"
        Dim DocumentElement As XmlDocument = New XmlDocument

        If File.Exists(Filename) Then
            ' Open the XML file
            DocumentElement.Load(Filename)

            ' Create an attribute and add it to the root element
            DocumentElement.DocumentElement.SetAttribute("FileDesc", _
                               "Personal Video Collection")
            DocumentElement.Save("videos.xml")
        End If
    End Sub
End Class

From the above videos.xml file, this code would result in:

<?xml version="1.0" encoding="utf-8"?>
<videos FileDesc="Personal Video Collection">
  <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>

Practical Learning: Creating an Attribute

  1. To set attributes of a node, change the file as follows:
     
    Imports System.IO
    Imports System.Xml
    
    Public Class RealEstate
    
        Private Sub btnNewProperty_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewProperty.Click
            ' Get a reference to the property editor
            Dim Editor As PropertyEditor = New PropertyEditor
    
            Dim Filename As String = "properties.xml"
    
            Dim RndNumber As Random = New Random
            Editor.txtPropertyCode.Text = RndNumber.Next(100, 999).ToString() & _
                                          "-" & RndNumber.Next(100, 999)
    
            If Editor.ShowDialog() = DialogResult.OK Then
                Dim PropertyCode As String
                Dim PropertyType As String
                Dim Location As String
                Dim SaleStatus As String
                Dim Stories As Integer, Bedrooms As Integer
                Dim Bathrooms As Single
                Dim MarketValue As Double
    
                ' We will need a reference to the XML document
                Dim DOMProperties As XmlDocument = New XmlDocument
    
                ' Find out if the file exists already
                ' If it doesn't, then create it
                If Not File.Exists(Filename) Then
                    DOMProperties.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" & _
                                      "<Listing></Listing>")
                    DOMProperties.Save(Filename)
                End If
    
                ' Open the XML file
                DOMProperties.Load(Filename)
    
                PropertyCode = Editor.txtPropertyCode.Text
                SaleStatus = Editor.cbxStatus.Text
                PropertyType = Editor.cbxPropertyTypes.Text
                Location = Editor.txtLocation.Text
                Stories = CInt(Editor.txtStories.Text)
                Bedrooms = CInt(Editor.txtBedrooms.Text)
                Bathrooms = CSng(Editor.txtBathrooms.Text)
                MarketValue = CDbl(Editor.txtMarketValue.Text)
    
                ' Get a reference to the root element
                Dim RootElement As XmlElement = DOMProperties.DocumentElement
                ' Create a node named Property
                Dim PropertyElement As XmlElement = DOMProperties.CreateElement("Property")
    
                ' Create an attribute for the Propety node
                PropertyElement.SetAttribute("Code", PropertyCode)
    
                ' Create an attribute for the Propety node
                PropertyElement.SetAttribute("Status", SaleStatus)
    
                ' Add it to the root element
                RootElement.AppendChild(PropertyElement)
    
                . . . No Change
    
                ' Save the XML file
                DOMProperties.Save(Filename)
            End If
        End Sub
    End Class
  2. Execute the application
  3. Click the New Property button
  4. Enter the following pieces of information:
     
    Status Sold
    Property Type Single Family
    Location Arlington Cemetery
    Stories 3
    Bedrooms 5
    Bathrooms 3.5
    Market Value 675880
  5. Click OK
  6. Close the form and return to your programming environment
  7. In Visual Studio, access the properties.xml tab to see the file (the value of the Code attribute will be different from yours):
     
    <?xml version="1.0" encoding="utf-8"?>
    <Listing>
      <Property>
        <PropertyType>Single Family</PropertyType>
        <Location>White Oak</Location>
        <Stories>2</Stories>
        <Bedrooms>3</Bedrooms>
        <Bathrooms>2.50</Bathrooms>
        <MarketValue>365580.00</MarketValue>
      </Property>
      <Property Code="700-326" Status="Sold">
        <PropertyType>Single Family</PropertyType>
        <Location>Arlington Cemetery</Location>
        <Stories>3</Stories>
        <Bedrooms>5</Bedrooms>
        <Bathrooms>3.50</Bathrooms>
        <MarketValue>675880.00</MarketValue>
      </Property>
    </Listing>
  8. Display the RealEstate.vb file

Adding an Attribute to an 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 Function CreateAttribute(name As String) As XmlAttribute

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 Overridable Function SetAttributeNode(newAttr As XmlAttribute) As XmlAttribute

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 Sub btnDocument_Click(ByVal sender As System.Object, _
                              ByVal e As System.EventArgs) _
                              Handles btnDocument.Click
    Dim Filename As String = "videos.xml"
    Dim DocumentElement As XmlDocument = New XmlDocument

    If File.Exists(Filename) Then
        ' Open the XML file
        DocumentElement.Load(Filename)

        ' Create a new attribute
        Dim ISBNAttribute As XmlAttribute = DocumentElement.CreateAttribute("ISBN")
        ISBNAttribute.Value = "0-7907-3900-3"

        ' Get a list of elements whose names are Video
        Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
        ' Since we will look for a specific video, get the list of all titles
        Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

        ' Visit each title
        For i As Integer = 0 To ListOfTitles.Count - 1
            ' Look for a video whose title is "Her Alibi"
            If ListOfTitles(i).InnerText.Equals("Her Alibi") Then
                ' Once you find that video, add the new attribute to it
                CType(ListOfVideos(i), XmlElement).SetAttributeNode(ISBNAttribute)
            End If
        Next

        DocumentElement.Save("videos.xml")
    End If
End Sub

From the above Videos.xml file, this code would result in:

<?xml version="1.0" encoding="utf-8"?>
<videos FileDesc="Personal Video Collection">
  <video ISBN="0-7888-1623-3">
    <title 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 WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Practical Learning: Adding an Attribute to an Element

  1. To add a few attributes, change the file as follows:
     
    Imports System.IO
    Imports System.Xml
    
    Public Class RealEstate
    
        Private Sub btnNewProperty_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewProperty.Click
            ' Get a reference to the property editor
            Dim Editor As PropertyEditor = New PropertyEditor
            ' If this directory doesn't exist, create it
            Directory.CreateDirectory("C:\Altair Realtors")
            ' This is the XML file that holds the list of proeprties
            Dim Filename As String = "C:\Altair Realtors\properties.xml"
    
            Dim RndNumber As Random = New Random
            Editor.txtPropertyCode.Text = RndNumber.Next(100, 999) & _
                                          "-" & RndNumber.Next(100, 999).ToString()
    
            If Editor.ShowDialog() = DialogResult.OK Then
                Dim PropertyCode As String, PropertyType As String
                Dim Location As String, SaleStatus As String
                Dim Style As String, Condition As String
                Dim YearBuilt As Integer, Stories As Integer, Bedrooms As Integer
                Dim Bathrooms As Single
                Dim MarketValue As Double
    
                ' We will need a reference to the XML document
                Dim DOMProperties As XmlDocument = New XmlDocument
    
                ' Find out if the file exists already
                ' If it doesn't, then create it
                If Not File.Exists(Filename) Then
                    DOMProperties.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" & _
                                          "<Listing></Listing>")
                    DOMProperties.Save(Filename)
                End If
    
                ' Open the XML file
                DOMProperties.Load(Filename)
    
                PropertyCode = Editor.txtPropertyCode.Text
                Location = Editor.txtLocation.Text
                SaleStatus = Editor.cbxStatus.Text
                YearBuilt = CInt(Editor.txtYearBuilt.Text)
                PropertyType = Editor.cbxPropertyTypes.Text
                Style = Editor.cbxStyle.Text
                Condition = Editor.cbxConditions.Text
                Bedrooms = CInt(Editor.txtBedrooms.Text)
                Bathrooms = CSng(Editor.txtBathrooms.Text)
                MarketValue = CDbl(Editor.txtMarketValue.Text)
    
                ' Get a reference to the root element
                Dim RootElement As XmlElement = DOMProperties.DocumentElement
                ' Create a node named Property
                Dim PropertyElement As XmlElement = DOMProperties.CreateElement("Property")
    
                ' Create an attribute for the Propety node
                PropertyElement.SetAttribute("Code", PropertyCode)
    
                ' Create an attribute for the Propety node
                PropertyElement.SetAttribute("Status", SaleStatus)
                ' Add it to the root element
                RootElement.AppendChild(PropertyElement)
    
                ' Create a node named Property
                PropertyElement = DOMProperties.CreateElement("DateListed")
                RootElement.LastChild.AppendChild(PropertyElement)
    
                ' Create an attribute for the DateListed element
                Dim atrProperty As XmlAttribute = DOMProperties.CreateAttribute("YearBuilt")
                atrProperty.Value = YearBuilt
                PropertyElement.SetAttributeNode(atrProperty)
    
                ' Create a node named PropertyType
                PropertyElement = DOMProperties.CreateElement("PropertyType")
                Dim TextProperty As XmlText = DOMProperties.CreateTextNode(PropertyType)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create an attribute for the PropertyType element
                atrProperty = DOMProperties.CreateAttribute("Style")
                atrProperty.Value = Style
                PropertyElement.SetAttributeNode(atrProperty)
    
                ' Create an attribute for the Condition element
                atrProperty = DOMProperties.CreateAttribute("Condition")
                atrProperty.Value = Condition
                PropertyElement.SetAttributeNode(atrProperty)
    
                ' Create a node named Location
                PropertyElement = DOMProperties.CreateElement("Location")
                TextProperty = DOMProperties.CreateTextNode(Location)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Stories
                PropertyElement = DOMProperties.CreateElement("Stories")
                TextProperty = DOMProperties.CreateTextNode(Stories)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Bedrooms
                PropertyElement = DOMProperties.CreateElement("Bedrooms")
                TextProperty = DOMProperties.CreateTextNode(Bedrooms)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Bathrooms
                PropertyElement = DOMProperties.CreateElement("Bathrooms")
                TextProperty = DOMProperties.CreateTextNode(FormatNumber(Bathrooms))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named MarketValue
                PropertyElement = DOMProperties.CreateElement("MarketValue")
                TextProperty = DOMProperties.CreateTextNode(FormatNumber(MarketValue))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Save the XML file
                DOMProperties.Save(Filename)
            End If
        End Sub
    End Class
  2. Save the file

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 do not want or that you do not 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 Overridable Function RemoveAttributeAt(i As Integer) As XmlNode

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

Using the XmlElement.RemoveAtributeAt() 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(name As String)

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 it 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 ( _
	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 does not 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:

<video ISBN="0-7888-1623-3" ScreenRatio="Standard" SoundtrackAvailable="True" />

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. The XmlAttributeCollection class has the following syntax:

Public NotInheritable Class XmlAttributeCollection _
	Inherits XmlNamedNodeMap _
	Implements ICollection, IEnumerable

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. Consider the following XML document:

<?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>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

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 Function Prepend(node As XmlAttribute) As XmlAttribute

Here is an  example:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
    Dim Filename As String = "videos.xml"
    Dim DocumentElement As XmlDocument = New XmlDocument

    If File.Exists(Filename) Then
        ' Open the XML file
        DocumentElement.Load(Filename)

        ' Create a new attribute
        Dim ISBNAttribute As XmlAttribute = DocumentElement.CreateAttribute("ISBN")
        ISBNAttribute.Value = "0-7907-3900-3"

        ' Get a list of elements whose names are Video
        Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
        ' Since we will look for a specific video, get the list of all titles
        Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

        ' Visit each title
        For i As Integer = 0 To ListOfTitles.Count - 1
            ' Look for a video whose title is "Godzilla"
            If ListOfTitles(i).InnerText.Equals("Godzilla") Then
                ' Once you find that video, "prepend" the new attribute to it
                ListOfVideos(i).Attributes.Prepend(ISBNAttribute)
            End If
        Next

        DocumentElement.Save("videos.xml")
    End If
End Sub

This would produce:

<?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 ISBN="0-7907-3900-3">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Notice that once again we used only one attribute. Image an element of your document has many attributes:

<?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 ISBN="0-7907-3900-3" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

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

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

Here is an example of calling this method:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
        Dim Filename As String = "videos.xml"
        Dim DocumentElement As XmlDocument = New XmlDocument

        If File.Exists(Filename) Then
            ' Open the XML file
            DocumentElement.Load(Filename)

            ' Create a new attribute
            Dim SystemAttribute As XmlAttribute = DocumentElement.CreateAttribute("System")
            SystemAttribute.Value = "NTSC"

            ' Get a list of elements whose names are Video
            Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
            ' Since we will look for a specific video, get the list of all titles
            Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

            ' Visit each title
            For i As Integer = 0 To ListOfTitles.Count - 1
                ' Look for a video whose title is "Her Alibi"
                If ListOfTitles(i).InnerText.Equals("Godzilla") Then
                    ' Define the attribute that will be used as referenced point
                    Dim WidescreenAttribute As XmlAttribute = ListOfVideos(i).Attributes("widescreen")
                    ' Once you find that video, add the new attribute to it
                    ListOfVideos(i).Attributes.InsertBefore(SystemAttribute, WidescreenAttribute)
                End If
            Next

            DocumentElement.Save("videos.xml")
        End If
End Sub

This would produce:

<?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 ISBN="0-7907-3900-3" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

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

public virtual XmlAttribute InsertAfter(XmlAttribute newNode,
					XmlAttribute refNode)

Here is an example:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
        Dim Filename As String = "videos.xml"
        Dim DocumentElement As XmlDocument = New XmlDocument

        If File.Exists(Filename) Then
            ' Open the XML file
            DocumentElement.Load(Filename)

            ' Create a new attribute
            Dim YearAttribute As XmlAttribute = DocumentElement.CreateAttribute("yearreleased")
            YearAttribute.Value = "1998"

            ' Get a list of elements whose names are Video
            Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
            ' Since we will look for a specific video, get the list of all titles
            Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

            ' Visit each title
            For i As Integer = 0 To ListOfTitles.Count - 1
                ' Look for a video whose title is "Her Alibi"
                If ListOfTitles(i).InnerText.Equals("Godzilla") Then
                    ' Define the attribute that will be used as referenced point
                    Dim ISBNAttribute As XmlAttribute = ListOfVideos(i).Attributes("ISBN")
                    ' Once you find that video, add the new attribute to it
                    ListOfVideos(i).Attributes.InsertAfter(YearAttribute, ISBNAttribute)
                End If
            Next

            DocumentElement.Save("videos.xml")
        End If
End Sub

This would produce:

<?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 ISBN="0-7907-3900-3" yearreleased="1998" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

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

Consider the following document:

<?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 ISBN="0-7907-3900-3" yearreleased="1998" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3" closedcaption="true">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Here is an example of calling the XmlAttributeCollection.Append() method:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
        Dim Filename As String = "videos.xml"
        Dim DocumentElement As XmlDocument = New XmlDocument

        If File.Exists(Filename) Then
            ' Open the XML file
            DocumentElement.Load(Filename)

            ' Create a new attribute
            Dim ProducedByAttribute As XmlAttribute = DocumentElement.CreateAttribute("producedby")
            ProducedByAttribute.Value = "Keith Barish"

            ' Get a list of elements whose names are Video
            Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
            ' Since we will look for a specific video, get the list of all titles
            Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

            ' Visit each title
            For i As Integer = 0 To ListOfTitles.Count - 1
                ' Look for a video whose title is "Her Alibi"
                If ListOfTitles(i).InnerText.Equals("Her Alibi") Then
                    ' Once you find that video, add the new attribute to it
                    ListOfVideos(i).Attributes.Append(ProducedByAttribute)
                End If
            Next

            DocumentElement.Save("videos.xml")
        End If
End Sub

This would produce:

<?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 ISBN="0-7907-3900-3" yearreleased="1998" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3" closedcaption="true" producedby="Keith Barish">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Practical Learning: Adding Attributes

  1. To add a few attributes, change the file as follows:
     
    Imports System.IO
    Imports System.Xml
    
    Public Class RealEstate
    
        Private Sub btnNewProperty_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles btnNewProperty.Click
            ' Get a reference to the property editor
            Dim Editor As PropertyEditor = New PropertyEditor
            ' If this directory doesn't exist, create it
            Dim FolderName As String = "C:\Altair Realtors"
            Directory.CreateDirectory(FolderName)
            ' This is the XML file that holds the list of proeprties
            Dim Filename As String = "C:\Altair Realtors\properties.xml"
    
            Dim RndNumber As Random = New Random
            Editor.txtPropertyCode.Text = RndNumber.Next(100, 999) & _
                                          "-" & RndNumber.Next(100, 999)
            Dim strPicturePath As String
    
            If Editor.ShowDialog() = DialogResult.OK Then
                Dim PropertyCode As String, PropertyType As String
                Dim Location As String, SaleStatus As String
                Dim Style As String, Condition As String
                Dim Address As String, City As String, State As String
                Dim ZIPCode As String, Description As String
                Dim DateListed As Date
                Dim YearBuilt As Integer, Stories As Integer, Bedrooms As Integer
                Dim Bathrooms As Single
                Dim MarketValue As Double
    
                ' We will need a reference to the XML document
                Dim DOMProperties As XmlDocument = New XmlDocument
    
                ' Find out if the file exists already
                ' If it doesn't, then create it
                If Not File.Exists(Filename) Then
                    DOMProperties.LoadXml("<?xml version=""1.0"" encoding=""utf-8""?>" & _
                                          "<Listing></Listing>")
                    DOMProperties.Save(Filename)
                End If
    
                ' Open the XML file
                DOMProperties.Load(Filename)
    
                PropertyCode = Editor.txtPropertyCode.Text
                SaleStatus = Editor.cbxStatus.Text
                DateListed = Editor.dtpDateListed.Value
                YearBuilt = CInt(Editor.txtYearBuilt.Text)
                PropertyType = Editor.cbxPropertyTypes.Text
                Style = Editor.cbxStyle.Text
                Condition = Editor.cbxConditions.Text
                Location = Editor.txtLocation.Text
                Address = Editor.txtAddress.Text
                City = Editor.txtCity.Text
                State = Editor.cbxStates.Text
                ZIPCode = Editor.txtZIPCode.Text
                Stories = CInt(Editor.txtStories.Text)
                Bedrooms = CInt(Editor.txtBedrooms.Text)
                Bathrooms = CSng(Editor.txtBathrooms.Text)
                Description = Editor.txtDescription.Text
                MarketValue = CDbl(Editor.txtMarketValue.Text)
                strPicturePath = Editor.txtPicturePath.Text
    
                ' Get a reference to the root element
                Dim RootElement As XmlElement = DOMProperties.DocumentElement
                ' Create a node named Property
                Dim PropertyElement As XmlElement = DOMProperties.CreateElement("Property")
    
                ' Create an attribute for the Propety node
                PropertyElement.SetAttribute("Code", PropertyCode)
    
                ' Create an attribute for the Propety node
                PropertyElement.SetAttribute("Status", SaleStatus)
                ' Add it to the root element
                RootElement.AppendChild(PropertyElement)
    
                ' Create a node named Property
                PropertyElement = DOMProperties.CreateElement("DateListed")
                Dim TextProperty As XmlText = DOMProperties.CreateTextNode(DateListed.ToString("d"))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
                RootElement.LastChild.AppendChild(PropertyElement)
    
                ' Create an attribute for the DateListed element
                Dim atrProperty As XmlAttribute = DOMProperties.CreateAttribute("YearBuilt")
                atrProperty.Value = YearBuilt
                PropertyElement.SetAttributeNode(atrProperty)
    
                ' Create a node named PropertyType
                PropertyElement = DOMProperties.CreateElement("PropertyType")
                TextProperty = DOMProperties.CreateTextNode(PropertyType)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create an attribute for the PropertyType element
                atrProperty = DOMProperties.CreateAttribute("Style")
                atrProperty.Value = Style
                PropertyElement.SetAttributeNode(atrProperty)
    
                ' Create an attribute for the PropertyType element
                atrProperty = DOMProperties.CreateAttribute("Condition")
                atrProperty.Value = Condition
                PropertyElement.SetAttributeNode(atrProperty)
    
                ' Create a node named Location
                PropertyElement = DOMProperties.CreateElement("Location")
                TextProperty = DOMProperties.CreateTextNode(Location)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create some attributes for the Location element
                atrProperty = DOMProperties.CreateAttribute("Address")
                atrProperty.Value = Address
                PropertyElement.Attributes.Append(atrProperty)
    
                atrProperty = DOMProperties.CreateAttribute("City")
                atrProperty.Value = City
                PropertyElement.Attributes.Append(atrProperty)
    
                atrProperty = DOMProperties.CreateAttribute("State")
                atrProperty.Value = State
                PropertyElement.Attributes.Append(atrProperty)
    
                atrProperty = DOMProperties.CreateAttribute("ZIPCode")
                atrProperty.Value = ZIPCode
                PropertyElement.Attributes.Append(atrProperty)
    
                ' Create a node named Stories
                PropertyElement = DOMProperties.CreateElement("Stories")
                TextProperty = DOMProperties.CreateTextNode(Stories.ToString())
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Bedrooms
                PropertyElement = DOMProperties.CreateElement("Bedrooms")
                TextProperty = DOMProperties.CreateTextNode(Bedrooms.ToString())
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Bathrooms
                PropertyElement = DOMProperties.CreateElement("Bathrooms")
                TextProperty = DOMProperties.CreateTextNode(FormatNumber(Bathrooms))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named MarketValue
                PropertyElement = DOMProperties.CreateElement("MarketValue")
                TextProperty = DOMProperties.CreateTextNode(FormatNumber(MarketValue))
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Create a node named Description
                PropertyElement = DOMProperties.CreateElement("Description")
                TextProperty = DOMProperties.CreateTextNode(Description)
                RootElement.LastChild.AppendChild(PropertyElement)
                RootElement.LastChild.LastChild.AppendChild(TextProperty)
    
                ' Save the XML file
                DOMProperties.Save(Filename)
    
                If strPicturePath.Length <> 0 Then
                    ' The following code gets a reference to the picture's name 
                    Dim flePicture As FileInfo = New FileInfo(strPicturePath)
                    ' Then it copies it to the directory of this business
                    ' It changes its name to be the same as the property code
                    flePicture.CopyTo("C:\Altair Realtors""" & _
                                      PropertyCode & _
                                      flePicture.Extension)
                End If
    
                ShowListing()
    
                If lvwProperties.Items.Count > 0 Then
                    lvwProperties.Items(0).Selected = True
                End If
            End If
        End Sub
    
        Private Sub ShowListing()
    
        End Sub
    End Class
  2. Execute the application and create a few properties
  3. Close the form and return to your programming environment

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 ReadOnly Property ItemOf(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 item 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(name As String) As XmlAttribute

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

Practical Learning: Accessing Some Attributes

  1. Implement the ShowListing procedure as follows:
    Private Sub ShowListing()
            Dim DOMProperties As XmlDocument = New XmlDocument
            Dim Filename As String = "C:\Altair Realtors\properties.xml"
    
            If File.Exists(Filename) Then
                lvwProperties.Items.Clear()
    
                DOMProperties.Load(Filename)
                Dim PropertyElement As XmlElement = DOMProperties.DocumentElement
                Dim ListOfProperties As XmlNodeList = PropertyElement.ChildNodes
    
                Dim i As Integer = 1
    
                For Each Node As XmlNode In ListOfProperties
                    Dim lviProperty As ListViewItem = New ListViewItem(i)
    
                    lviProperty.SubItems.Add(Node.Attributes(0).InnerText)
                    lviProperty.SubItems.Add(Node.FirstChild.NextSibling.InnerText)
                    lviProperty.SubItems.Add(Node.FirstChild.NextSibling.Attributes(1).InnerText)
                    lviProperty.SubItems.Add(Node.FirstChild.NextSibling.NextSibling.InnerText)
                    lviProperty.SubItems.Add(Node.FirstChild.NextSibling.NextSibling.NextSibling.InnerText)
                    lviProperty.SubItems.Add( _
    Node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.InnerText)
                    lviProperty.SubItems.Add( _
    Node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText)
                    lviProperty.SubItems.Add( _
    Node.FirstChild.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.NextSibling.InnerText)
                    lvwProperties.Items.Add(lviProperty)
                    i = i + 1
                Next
    
                txtDescription.Text = ListOfProperties(0)("Description").InnerText
            End If
    End Sub 
  2. In the Class Name combo box, select (RealEstate Events)
  3. In the Method Name combo box, select Load and implement the event as follows:
     
    Private Sub RealEstate_Load(ByVal sender As Object, _
                                    ByVal e As System.EventArgs) _
                                    Handles Me.Load
            ShowListing()
    
            If lvwProperties.Items.Count > 0 Then
                lvwProperties.Items(0).Selected = True
            End If
    End Sub
  4. In the Class name combo box, select lvwProperties
  5. In the Method Name combo box, select SelectedIndexChanged and implement the event as follows:
     
    Private Sub lvwProperties_SelectedIndexChanged(ByVal sender As Object, _
                                                   ByVal e As System.EventArgs) _
                                          Handles lvwProperties.SelectedIndexChanged
        If (lvwProperties.SelectedItems.Count = 0) Or _
           (lvwProperties.SelectedItems.Count > 1) Then
            Exit Sub
        End If
    
        Dim PropertyCode As String = lvwProperties.SelectedItems(0).SubItems(1).Text
    
        ' Make a list of the picture files
        Dim FolderName As String = "C:\Altair Realtors"
        Dim dirProperties As DirectoryInfo = New DirectoryInfo(FolderName)
        Dim PictureFiles() As FileInfo = dirProperties.GetFiles()
    
        ' Look for a file that holds the same name as the item number
        For Each fle As FileInfo In PictureFiles
            ' Get the name of the file without its extension
            Dim fwe As String = Path.GetFileNameWithoutExtension(fle.FullName)
             If fwe = PropertyCode Then
                pbxProperty.Image = Image.FromFile(FolderName & _
                      """" & PropertyCode + fle.Extension)
            End If
        Next
    
        Dim DOMProperties As XmlDocument = New XmlDocument
        Dim Filename As String = "C:\Altair Realtors\properties.xml"
    
        If File.Exists(Filename) Then
            DOMProperties.Load(Filename)
            Dim PropertyElement As XmlElement = DOMProperties.DocumentElement
            Dim ListOfProperties As XmlNodeList = PropertyElement.ChildNodes
    
            For Each Node As XmlNode In ListOfProperties
                If Node.Attributes(0).InnerText = PropertyCode Then
                    txtDescription.Text = Node("Description").InnerText
                End If
            Next
        End If
    End Sub
  6. In the Class Name combo box, select btnClose
  7. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub btnClose_Click(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) _
                                   Handles btnClose.Click
            End
    End Sub
  8. Execute the application

Deleting an Attribute

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. Consider the following document:

<?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 ISBN="0-7907-3900-3" yearreleased="1998" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3" closedcaption="true" producedby="Keith Barish">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Here is an example of deleting an attribute by calling the XmlAttributeCollection.RemoveAt() method:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
    Dim Filename As String = "videos.xml"
    Dim DocumentElement As XmlDocument = New XmlDocument

    If File.Exists(Filename) Then
        ' Open the XML file
        DocumentElement.Load(Filename)

        ' Get a list of elements whose names are Video
        Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
        ' Since we will look for a specific video, get the list of all titles
        Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

        ' Visit each title
        For i As Integer = 0 To ListOfTitles.Count - 1
            ' Look for a video whose title is "Her Alibi"
            If ListOfTitles(i).InnerText.Equals("Godzilla") Then
                ' Once you find that video, delete its second attribute
                ListOfVideos(i).Attributes.RemoveAt(1)
            End If
        Next

        DocumentElement.Save("videos.xml")
    End If
End Sub

This would produce:

<?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 ISBN="0-7907-3900-3" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3" closedcaption="true" producedby="Keith Barish">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

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 Function Remove(node As XmlAttribute) As XmlAttribute

This method takes as attribute the XmlAttribute identification of the attribute you want to remove. Here is an example of calling it:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
    Dim Filename As String = "videos.xml"
    Dim DocumentElement As XmlDocument = New XmlDocument

    If File.Exists(Filename) Then
        ' Open the XML file
        DocumentElement.Load(Filename)

        ' Get a list of elements whose names are Video
        Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
        ' Since we will look for a specific video, get the list of all titles
        Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

        ' Visit each title
        For i As Integer = 0 To ListOfTitles.Count - 1
            ' Look for a video whose title is "Her Alibi"
            If ListOfTitles(i).InnerText.Equals("Her Alibi") Then
                ' Define the attribute that should be deleted
                Dim CCAttribute As XmlAttribute = ListOfVideos(i).Attributes("closedcaption")
                ' If that attribute exists, delete it
                ListOfVideos(i).Attributes.Remove(CCAttribute)
            End If
        Next

        DocumentElement.Save("videos.xml")
    End If
End Sub

This would produce:

<?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 ISBN="0-7907-3900-3" System="NTSC" widescreen="true">
    <title>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3" producedby="Keith Barish">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

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 of calling it:

Private Sub btnDocument_Click(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs) _
                                  Handles btnDocument.Click
    Dim Filename As String = "videos.xml"
    Dim DocumentElement As XmlDocument = New XmlDocument

    If File.Exists(Filename) Then
        ' Open the XML file
        DocumentElement.Load(Filename)

        ' Get a list of elements whose names are Video
        Dim ListOfVideos As XmlNodeList = DocumentElement.GetElementsByTagName("video")
        ' Since we will look for a specific video, get the list of all titles
        Dim ListOfTitles As XmlNodeList = DocumentElement.GetElementsByTagName("title")

        ' Visit each title
        For i As Integer = 0 To ListOfTitles.Count - 1
            ' Look for a video whose title is "Her Alibi"
            If ListOfTitles(i).InnerText.Equals("Godzilla") Then
                ' Delete all attributes of the title of this video element
                ListOfVideos(i).Attributes.RemoveAll()
            End If
        Next

        DocumentElement.Save("videos.xml")
    End If
End Sub

This would produce:

<?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>Godzilla</title>
    <director>Roland Emmerich</director>
    <length>139 Minutes</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
  <video ISBN="0-7907-3900-3" producedby="Keith Barish">
    <title WrittenBy="Charlie Peter">Her Alibi</title>
    <director>Bruce Beresford</director>
    <length>94 Mins</length>
    <format>DVD</format>
    <rating>PG-13</rating>
  </video>
</videos>

Exercises

 

Altair Realtors

  1. Create a Windows Application named AltairRealtors1a following the same steps as this lesson
  2. Create big pictures of the properties (houses) and save them
  3. Configure the first form so that, if the user double-clicks the picture, another window opens and displays a bigger picture of the house or of the building
  4. Configure the first form so that, if the user double-clicks an item, the property editor opens and displays the corresponding property. Then, if the user modifies a value in the dialog box and clicks OK, you update the same property with the changed value(s)
  5. Make the necessary changes to the application to produce an XML document with the following additional elements and attributes
     
    <Listing>
        <Property Code"000-000" Status="">
            <DateListed YearBuilt=""></DateListed>
            <PropertyType Style="" Condition=""></PropertyType>
            <Location Address="" City="" State="" ZIPCode=""></Location>
            <Stories></Stories>
            <Bedrooms UpperFloor="4" LowerFloor="0" Basement="1">5</Bedrooms>
            <Bathrooms UpperFloor="2" LowerFloor="0.5" Basement="1">3.5</Bathrooms>
            <IndoorGarage Spaces="2">true</IndoorGarage>
            <FinishedBasement Entrance=
    	"Common/Rear" FinishedType="Recreation Room/Apartment">true</FinishedBasement>
            <Description></Description>
        </Property>
    </Listing>

 

 

Previous Copyright 2008, Yevol Next