In this section, we’ll move on to a more interesting component of LINQ, the LINQ to XML component. XML is gaining in popularity and acceptance, and Microsoft has decided to promote XML to a basic data type. Yes, XML is a data type like integers and strings! To understand how far VB is taking XML, type the following in a procedure or event handler:
Dim products = <Books>
<Book ISBN="0000000000001">
<Name>Book Title 1</Name>
<Price>11.95</Price>
</Book>
<Book ISBN="000000000002">
<Name>Book Title 2</Name>
<Price>10.25</Price>
</Book>
</Books>
Code language: HTML, XML (xml)
You need not worry too much about getting the document exactly right, because the editor works just like the XML Editor. Every time you type an opening tag, it inserts the matching closing tag and ensures that what you’re typing is a valid XML document. You can’t apply a schema to the XML document you’re creating, but you should expect this feature in a future version of Visual Studio.
You can create a new XML document in your code, but what can you do with it? We need a mechanism to manipulate the XML document with simple tools, and these tools are available through the following XML helper objects:
XDocument represents the XML document.
XComment represents a comment in the XML document.
XElement represents an XML element.
XAttribute represents an attribute in an XML element.
These objects can be used to access the document but also to create it. Instead of creating an XML document directly in your code, you can use the XML helper objects and a structural approach to create the same document. A simple XML document consists of elements, which may include attributes. To create a new XElement object, pass the element’s name and value to its constructor:
New XElement(element_name, element_value)
Code language: PHP (php)
The following statement will create a very simple XML document:
Dim XmlDoc = New XElement("Books")
MsgBox(XmlDoc.ToString)
Code language: PHP (php)
You will see the string <Books /> in a message box. This is a trivial, yet valid, XML document. To create the same book collection as we did earlier by using the helper objects, insert the following statements in a button’s Click event handler:
Dim doc = _
New XElement("Books", _
New XElement("Book", _
New XAttribute("ISBN", "0000000000001"), _
New XElement("Price", 11.95),_
New XElement("Name", "Book Title 1"),_
New XElement("Stock", _
New XAttribute("InStock", 12), _
New XAttribute("OnOrder", 24))), _
New XElement("Book", _
New XAttribute("ISBN", "0000000000002"), _
New XElement("Price", 10.25), _
New XElement("Name", "Book Title 2"), _
New XElement("Stock", _
New XAttribute("InStock", 7), _
New XAttribute("OnOrder", 10))))
Code language: PHP (php)
I’ve added a twist to the new document to demonstrate the use of multiple attributes in the same element. The Stock element contains two attributes, InStock and OnOrder. Each element’s value can be a basic data type, such as a string or a number, or another element. The Price element is a decimal value, and the Name element is a string. The Book element, however, contains three subelements: the Price, Name, and Stock elements.
The doc variable is of the XElement type. An XML document is not necessarily based on the XDocument class. The two basic operations you can perform with an XElement (and XDocument) object are to save it to a file and reload an XElement object from a file. The operations are performed with the Save and Load methods, which accept the file’s name as an argument.
Traversing XML Documents
Let’s look at how we can process an XML document by using the XML helper objects. If you’re familiar with the XML tools for manipulating XML documents from previous versions of Visual Basic, you’ll be impressed by the simplicity of the new approach. Each element may have one or more parent elements, which you can access via the Ancestors property, and one or more child elements, which you can access via the Descendants property. Both methods return a collection of XElement objects. In addition, elements may have attributes, which you can access via the Attribute property.
For Each book In doc.Elements("Book")
Debug.WriteLine("ISBN " & book.Attribute("ISBN").Value.ToString)
Debug.WriteLine(" Title: " & book.Descendants("Name").Value.ToString)
Debug.WriteLine(" Price: " & book.Descendants("Price").Value.ToString)
Dim stock = book.Element("Stock")
Debug.WriteLine(" Books in stock " & stock.Attribute("InStock").Value)
Debug.WriteLine(" Books on order " & stock.Attribute("OnOrder").Value)
Next
Code language: JavaScript (javascript)
The loop iterates through the Book elements in the XML file. The expression doc.Elements (“Book”) returns a collection of XElement objects, each of which has an Attribute property and a Descendants property. The Attribute property lets you access each attribute of the current element by name. The Descendants property returns a collection of XElement objects, one for each subelement of the element represented by the book XElement. One of the elements, the Stock element, has its own attributes. To read their values, the code creates a variable that represents the Stock element and uses its Attribute property to retrieve an attribute by name. The output of the preceding code segment is shown here:
ISBN 0000000000001
Title: Book Title 1
Price: 32.3
Books in stock 12
Books on order 24
ISBN 0000000000002
Title: Book Title 2
Price: 12.55
Books in stock 7
Books on order 10
Code language: CSS (css)
There’s a shorthand notation for accessing attributes, elements, and descendants in an XML file: The @ symbol is shorthand for the Attribute property, a pair of angle brackets (<>) is shorthand for the Element property, and two periods (..) are shorthand for the Descendants property. The following code segment is identical to the preceding one, only this time I’m using the shorthand notation. The output will be exactly the same as before.
For Each book In doc.Elements("Book")
Debug.WriteLine("ISBN " & book.@ISBN.ToString)
Debug.WriteLine(" Title: " & _
book...<Name>.Value.ToString)
Debug.WriteLine(" Price: " & _
book...<Price>.Value.ToString)
Dim stock = book.Element("Stock")
Debug.WriteLine(" Books in stock " & _
[email protected])
Debug.WriteLine(" Books on order " & _
[email protected])
Next
Code language: CSS (css)
Notice that attributes are returned as strings and have no Value property.