You are here:   XML
  |  Login

Introduction To XML


 XML although similar to HTML was really developed to serve a different purpose. XML was designed to describe data and to focus on what data is. HTML was designed to display data and to focus on how data looks.

Some Quick Bullets about XML

  • XML stands for E X tensible M arkup L anguage
  • XML is a markup language much like HTML
  • XML was designed to describe data
  • XML tags are not predefined. You must define your own tags
  • XML uses a Document Type Definition (DTD) or an XML Schema to describe the data
  • XML with a DTD or XML Schema is designed to be self-descriptive
  • XML is a W3C Recommendation

XML was really designed to do nothing more than carry data. Here is a simple example of describing a note: 

<note>
<to>Glenn</to>
<from>Joe</from>
<heading>Reminder</heading>
<body>Don't forget to grade my assignments</body>
</note>

 

The note has a header and a message body. It also has sender and receiver information. Still, this XML document does not DO anything. It is just pure information wrapped in XML tags. Someone must write a piece of software to send, receive or display it.

XML tags are not predefined. You must "invent" your own tags.

The tags used to mark up HTML documents and the structure of HTML documents are predefined. The author of HTML documents can only use tags that are defined in the HTML standard (like <p>, <h1>, etc.).

XML allows the author to define his or her own tags and document structure.

The tags in the example above (like <to> and <from>) are not defined in any XML standard. These tags are "invented" by the author of the XML document.

All XML elements must have a closing tag

With XML, it is illegal to omit the closing tag.

It used to be that some html tags did not require a closing tag. Elements like:

<br>

for instance. The W3C has made changes to the html standard so that all html tags need a closing tag. The <br> tag now becomes <br /> the / is signifies that closing. This change brings the XML and HTML standards closer together.

XML tags are case sensitive

Unlike HTML, XML tags are case sensitive.

With XML, the tag <Letter> is different from the tag <letter>.

Opening and closing tags must therefore be written with the same case:  

<Message>This is incorrect</message>
<message>This is correct</message>
 

 

All XML documents must have a root element


 All XML documents must contain a single tag pair to define a root element.

All other elements must be within this root element.

All elements can have sub elements (child elements). Sub elements must be correctly nested within their parent element:

<root>
   <child>
      <subchild>
         ....
      </subchild>
    </child>
</root>

 

Attribute values must always be quoted


 With XML, it is illegal to omit quotation marks around attribute values. 

XML elements can have attributes in name/value pairs just like in HTML. In XML the attribute value must always be quoted. Study the two XML documents below. The first one is incorrect, the second is correct:  

<?xml version="1.0" encoding="ISO-8859-1"?>
<note date=12/11/2006>
<to>Glenn</to>
<from>Joe</from>
</note>

 

<?xml version="1.0" encoding="ISO-8859-1"?>
<note date="12/11/2002">
<to>Glenn</to>
<from>Joe</from>
</note>

 

The error in the first document is that the date attribute in the note element is not quoted.

This is correct: date="12/11/2002". This is incorrect: date=12/11/2002.

With XML, white space is preserved

With XML, the white space in your document is not truncated .

This is unlike HTML. With HTML, a sentence like this:

Hello              my name is Glenn,

will be displayed like this:

Hello my name is Glenn,

because HTML reduces multiple, consecutive white space characters to a single white space.

With XML, CR / LF is converted to LF

With XML, a new line is always stored as LF .

Do you know what a typewriter is? Well, a typewriter is a mechanical device which was used last century to produce printed documents. :-)

After you have typed one line of text on a typewriter, you have to manually return the printing carriage to the left margin position and manually feed the paper up one line.

In Windows applications, a new line is normally stored as a pair of characters: carriage return (CR) and line feed (LF). The character pair bears some resemblance to the typewriter actions of setting a new line. In Unix applications, a new line is normally stored as a LF character. Macintosh applications use only a CR character to store a new line.

Comments in XML

The syntax for writing comments in XML is similar to that of HTML.

<!-- This is a comment -->

XML Elements are Extensible

 

XML documents can be extended to carry more information.

Look at the following XML NOTE example:

<note>
<to>Glenn</to>
<from>Joe</from>
<body>Don't forget to grade my assignments!</body>
</note>

Imagine that an application has been created to extract the <to>, <from>, and <body> elements from the XML document to produce this output:

 

MESSAGE

To: Glenn
From: Joe

Don't forget to grade my assignments!

 

Suppose the author of the XML document added some extra information to it:

 

<note>
<date>2002-08-01</date>
<to>Glenn</to>
<from>Joe</from>
<heading>Reminder</heading>
<body>Don't forget to grade my assignments </body>
</note>

Should the application break or crash?

The answer is no. The application should still be able to find the <to>, <from>, and <body> elements in the XML document and produce the same output.
XML documents are Extensible

XML Elements have Relationships

Elements are related as parents and children.

To understand XML terminology, you have to know how relationships between XML elements are named, and how element content is described.

Imagine that this is a description of a book:

 

<book>
<title>My First XML</title>
<prod id="33-657" media="paper"></prod><chapter>Introduction to XML
<para>What is HTML</para>
<para>What is XML</para>
</chapter>

<chapter>XML Syntax
<para>Elements must have a closing tag</para>
<para>Elements must be properly nested</para>
</chapter>

</book>

 

Book is the root element . Title, prod, and chapter are child elements of book. Book is the parent element of title, prod, and chapter. Title, prod, and chapter are siblings (or sister elements ) because they have the same parent.

Elements have Content

Elements can have different content types.

An XML element is everything from (including) the element's start tag to (including) the element's end tag.

An element can have element content, mixed content, simple content, or empty content. An element can also have attributes .

In the example above, book has element content , because it contains other elements. Chapter has mixed content because it contains both text and other elements. Para has simple content (or text content ) because it contains only text. Prod has empty content , because it carries no information.

In the example above only the prod element has attributes . The attribute named id has the value "33-657". The attribute named media has the value "paper". 

Element Naming

XML elements must follow these naming rules:

  • Names can contain letters, numbers, and other characters
  • Names must not start with a number or punctuation character
  • Names must not start with the letters xml (or XML, or Xml, etc)
  • Names cannot contain spaces

Take care when you "invent" element names and follow these simple rules:

Any name can be used, no words are reserved, but the idea is to make names descriptive. Names with an underscore separator are nice.

Examples: <first_name>, <last_name>.

Avoid "-" and "." in names. For example, if you name something "first-name," it could be a mess if your software tries to subtract name from first. Or if you name something "first.name," your software may think that "name" is a property of the object "first."

Element names can be as long as you like, but don't exaggerate. Names should be short and simple, like this: <book_title> not like this: <the_title_of_the_book>. 

XML documents often have a corresponding database, in which fields exist corresponding to elements in the XML document. A good practice is to use the naming rules of your database for the elements in the XML documents.

Non-English letters like éòá are perfectly legal in XML element names, but watch out for problems if your software vendor doesn't support them.

The ":" should not be used in element names because it is reserved to be used for something called namespaces.

XML Attributes

XML elements can have attributes.

From HTML you will remember this: <IMG SRC="/portals/5/computer.gif">. The SRC attribute provides additional information about the IMG element.

In HTML (and in XML) attributes provide additional information about elements:

<img src="/portals/5/computer.gif">
<a href="demo.aspx">

Attributes often provide information that is not a part of the data. In the example below, the file type is irrelevant to the data, but important to the software that wants to manipulate the element:

<file type="gif">computer.gif</file>

Quote Styles, "female" or 'female'?

Attribute values must always be enclosed in quotes, but either single or double quotes can be used. For a person's sex, the person tag can be written like this:

<person sex = "female">

or

<person sex = 'female'>

Note: If the attribute value itself contains double quotes it is necessary to use single quotes, like in this example:

<gangster name='George "Shotgun" Ziegler'>

Use of Elements vs. Attributes

Data can be stored in child elements or in attributes.

Take a look at these examples:

<person sex="female"> <firstname>Anna</firstname> <lastname>Smith</lastname> </person>

<person> <sex>female</sex> <firstname>Anna</firstname> <lastname>Smith</lastname> </person>

In the first example sex is an attribute. In the last, sex is a child element. Both examples provide the same information.

There are no rules about when to use attributes, and when to use child elements. My experience is that attributes are handy in HTML, but in XML you should try to avoid them. Use child elements if the information feels like data.

A Better Way ?

It my be better to store data in child elements.

The following three XML documents contain exactly the same information:

A date attribute is used in the first example:

<note date="12/11/2006">
<to>Glenn</to>
<from>Joe</from>
<heading>Reminder</heading>
<body>Don't forget to grade my assignments!</body>
</note>


A date element is used in the second example:

<note>
<date>12/11/2006</date>
<to>Glenn</to>
<from>Joe</from>
<heading>Reminder</heading>
<body>Don't forget to grade my assignments!</body>
</note>

 

An expanded date element is used in the third: (THIS IS MY FAVORITE):

 

<note>
<date>
<day>12</day>
<month>11</month>
<year>2006</year>
</date>
<to>Glenn</to>
<from>Joe</from>
<heading>Reminder</heading>
<body>Don't forget to grade my assignments!</body>
</note>

Avoid using attributes?


 Should you avoid using attributes?

Some of the problems with using attributes are:

  • attributes cannot contain multiple values (child elements can)
  • attributes are not easily expandable (for future changes)
  • attributes cannot describe structures (child elements can)
  • attributes are more difficult to manipulate by program code
  • attribute values are not easy to test against a Document Type Definition (DTD) - which is used to define the legal elements of an XML document

If you use attributes as containers for data, you end up with documents that are difficult to read and maintain. Try to use elements to describe data. Use attributes only to provide information that is not relevant to the data.

Don't end up like this (this is not how XML should be used):

<note day="12" month="11" year="2006"
to="Glenn" from="Joe" heading="Reminder"
body="Don't forget to grade my assignments ">
</note>

An Exception to my Attribute rule


 Rules always have exceptions.

My rule about attributes has one exception:

Sometimes I assign ID references to elements. These ID references can be used to access XML elements in much the same way as the NAME or ID attributes in HTML. This example demonstrates this:

<messages>
<note id="p501">
<to>Glenn</to>
<from>Joe</from>
<heading>Reminder</heading>
<body>Don't forget to grade my assignments!</body>
</note>

<note id="p502">
<to>Joe</to>
<from>Glenn</from>
<heading>Re: Reminder</heading>
<body>I will take care of it </body>
</note>
</messages>

The ID in these examples is just a counter, or a unique identifier, to identify the different notes in the XML file, and not a part of the note data.

What I am trying to say here is that metadata (data about data) should be stored as attributes, and that data itself should be stored as elements.

"Well Formed" XML documents

A "Well Formed" XML document has correct XML syntax.

A "Well Formed" XML document is a document that conforms to the XML syntax rules that were described in the previous chapters:

You can check the syntax of your XML documents by opening them with a web browser like Internet Explorer. If it displays ok then you have a well formed document. If not, the IE will display an appropriate error.

 

 

Introduction


 

XML has become a very popular means for the exchange of data over the web and Microsoft has certainly jumped on the band wagon in a big way. The .NET framework has a great deal of functionality that allows you to easily read and write to xml documents. This section will cover reading and displaying xml files. To start with the XmlTextReader object will be looked at because it is probably the easiest object to use for reading xml documents.

Creating Your XML Document


 

When you create an ASP.NET application in Visual Studio a folder called App_Data gets created. This is where you want to put your xml file. To create an xml file right click on the App_Data folder and select add new item. From the Add New Item dialog select XML File and give your file a name: 

Adding an XML File
Add New Item Dialog Box. Select XML file
Add New Item Dialog Box. Select XML file
Solution Explorer
Xml file is added to the App_Data Folder
Xml file is added to the App_Data Folder

Example XML


For this example a ficticious menu for a chinese restraunt will be used to demonstrate how to use the XmlTextReader. Here is the contents of the file:

 

<?xml version="1.0" encoding="utf-8" ?>

<Restaurant>
<Information>
      <Name>Wongs Moo Shoo</Name>
      <Address>12 Ming Palace Place</Address>
      <Description>If you're really looking for Chinese food here, you've come to the wrong place!</Description>

</Information>

<Menu>
   <Meat>
      <Beef>
         <Dish>   
            <Name>Mongololian Beef</Name>
            <Price>$8.95</Price>
           <Description>Slices of beef with snow Peas, mushrooms, and vegetables</Description>
         </Dish>

          <Dish>
              <Name>Szechuan Spiced Beef</Name>
              <Price>$8.25</Price>
              <Description>Slices of beef with hot peppers, finely chopped nuts, bamboo shoots, green peppers</Description>
          </Dish>

           <Dish>
               <Name>Chef's Special</Name>
               <Price>$9.25</Price>
               <Description>Crispy noodles topped with shredded mixed vegetable and Barbecue Beef</Description>
           </Dish>
      </Beef>
   <Pork>

   <Dish>
       <Name>Hot and Sour Pork</Name>
       <Price>$6.95</Price>
       <Description>Pork tenderloin with diced bamboo shoots, onions, and pepperes in a hot and sour sauce</Description>
    </Dish>

     <Dish>
        <Name>Manarin Spareribs</Name>
        <Price>$7.75</Price>
        <Description>Spare ribs cooked with sweet rice vinegar</Description>
      </Dish>
   </Pork>

   <Chicken>
      <Dish>
          <Name>Hunan Chicken</Name>
          <Price>$8.25</Price>
          <Description>Marinated chicken with garlic, bamboo shoots, and scallions sauteed in hot and spicy sauce</Description>
      </Dish>

      <Dish>
          <Name>Lemon Fried Chicken</Name>
          <Price>$7.25</Price>
          <Description>Breast of Chicken Deep Fried With Lemon Sauce</Description>
      </Dish>

      <Dish>
          <Name>Kung Pao Chicken</Name>
          <Price>$7.95</Price>
          <Description>Boneless chicken cubes, red peppers, peanuts, celery, mushrooms, and peas in a spicy hot sauce</Description>
      </Dish>
   </Chicken>
</Meat>

<Seafood>
   <Fish>
      <Dish>
         <Name>Sweet and Sour Fish</Name>
         <Price>$8.95</Price>
      </Dish>

      <Dish>
         <Name>Steamed Salmon with Black Bean Sauce</Name>
         <Price>$10.95</Price>
      </Dish>
   </Fish>

   <Shellfish>
      <Dish>
         <Name>Mixed Seafood Delight</Name>
         <Price>$13.25</Price>
         <Description>Crab, shrimps, and scallops cooked with broccoli</Description>
      </Dish>

      <Dish>
         <Name>Spiced Oysters</Name>
         <Price>$9.25</Price>
         <Description>Marinated oysters with garlic, ginger, bay leaves, red pepper, and parsley</Description>
      </Dish>
   </Shellfish>
 </Seafood>

</Menu>
</Restaurant>

XmlTextReader Class


 

 In order to use the XMLTextReader/Writer classe, you must first include the System.XML namespace:

using System.Xml;

Reading and XML Document


 

 Once the correct namespace has been included, the next step is to create an instance of the XmlTextReader object. The class has an overloaded constructor that allows you to set the path and the name of the file to be read:

XmlTextReader xml = new XmlTextReader(Server.MapPath("~/App_Data/menu.xml"));

A word about Server.MapPath


 The Server object has many usefull methods and properties. Maybe one of the most useful of these is the MapPath method. The MapPath method can be used to map the actual physical path of where your project files are on the server. This is usefull becuase typically your files are put into a virtual folder and its name has nothing to do where it physically is. The MapPath method figures it out for you. As long as you don't change the names and tree structure of your project folders from your development system and the web server, the MapPath Method can be used to locate where a particular file is. In the above example, the MapPath method is used to locate the root folder of the project and to map that to a file called menu.xml. If you were to simply print out the MapPath information, You would probably see something like this:

 c:\inetpub\wwwroot\xmlTest\App_Data\menu.xml

The MapPath method doesn't actuall check to see if the file menu.xml exists, it just creates the path to where the files would be located on the server. It is up to you to make sure that the files are located where you want them.

The Read() Method


 

Once an XmlTextReader object has been created, it can then be used to read the contents of the file. The object contains a method called Read that will read a line of file. Each call to the read method reads the next successive line in the file. This means that if you want to read the entire contents of the file the method will have to be put in a loop:

 

The read method will fail when there is no more data to read and the loop will the be exited.

Checking For Node Types


 

 Once a line of the file has been read you can use the NodeType property to check the node type of the xml file. There are several node types to look for so it is typical to put the node type in a switch statement:

 Notice that the NodeType returned from the XmlTextReader object can be checked agains an XmlNodeType.

The following is a list of the NodeTypes that can be checked:

 Member Name Description 
 Attribute

Supported by the .NET Compact Framework

 An attribute.

Example XML: id='123'

An Attribute node can have the following child node types: Text and EntityReference . The Attribute node does not appear as the child node of any other node type. It is not considered a child node of an Element .

 CDATA

Supported by the .NET Compact Framework.

 A CDATA section.

Example XML: <![CDATA[my

escaped text]]>

CDATA sections are used to escape blocks of text that would otherwise be recognized as markup. A CDATA node cannot have any child nodes. It can appear as the child of the DocumentFragment , EntityReference , and Element nodes.

 Comment

Supported by the .NET Compact Framework.

 A comment.

Example XML: <!-- my comment -->

A Comment node cannot have any child nodes. It can appear as the child of the Document , DocumentFragment , Element , and EntityReference nodes.

 Document

Supported by the .NET Compact Framework.

 A document object that, as the root of the document tree, provides access to the entire XML document.

A Document node can have the following child node types: XmlDeclaration , Element (maximum of one), ProcessingInstruction , Comment , and DocumentType . It cannot appear as the child of any node types.

 DocumentFragment

Supported by the .NET Compact Framework

 A document fragment.

The DocumentFragment node associates a node or subtree with a document without actually being contained within the document. A DocumentFragment node can have the following child node types: Element , ProcessingInstruction , Comment , Text , CDATA , and EntityReference . It cannot appear as the child of any node types.

 DocumentType

Supported by the .NET Compact Framework.

 The document type declaration, indicated by the following tag.

Example XML: <!DOCTYPE ...>

A DocumentType node can have the following child node types: Notation and Entity . It can appear as the child of the Document node.

 Element

Supported by the .NET Compact Framework.

 An element.

Example XML: <item> An Element node can have the following child node types: Element , Text , Comment , ProcessingInstruction , CDATA , and EntityReference . It can be the child of the Document , DocumentFragment , EntityReference , and Element nodes.

 EndElement

Supported by the .NET Compact Framework

 An end element tag.

Example XML: </item>

Returned when XmlReader gets to the end of an element.

 EndEntity  Returned when XmlReader gets to the end of the entity replacement as a result of a call to ResolveEntity
 Entity  An entity declaration.

Example XML: <!ENTITY ...>

An Entity node can have child nodes that represent the expanded entity (for example, Text and EntityReference nodes). It can appear as the child of the DocumentType node.

 EntityReference  A reference to an entity.

Example XML: &num;

An EntityReference node can have the following child node types: Element , ProcessingInstruction , Comment , Text , CDATA , and EntityReference . It can appear as the child of the Attribute , DocumentFragment , Element , and EntityReference nodes.

 None  This is returned by the XmlReader if a Read method has not been called.
 Notation  A notation in the document type declaration.

Example XML: <!NOTATION ...>

A Notation node cannot have any child nodes. It can appear as the child of the DocumentType node.

 ProcessingInstruction  A processing instruction.

Example XML: <?pi test?>

A ProcessingInstruction node cannot have any child nodes. It can appear as the child of the Document , DocumentFragment , Element , and EntityReference nodes.

 SignificantWhitespace  White space between markup in a mixed content model or white space within the xml:space="preserve" scope.
 Text  The text content of a node.

A Text node cannot have any child nodes. It can appear as the child node of the Attribute , DocumentFragment , Element , and EntityReference nodes.

 Whitespace  White space between markup.
 XmlDeclaration  The XML declaration.

Example XML: <?xml version='1.0'?>

The XmlDeclaration node must be the first node in the document. It cannot have children. It is a child of the Document node. It can have attributes that provide version and encoding information

Putting it Together


The last piece of the puzzle is to put it all together to read the contents of an xml file. The example that follows simply reads each element and writes it to a TextBox. Basically the output will look like opening the xml file with a text editor. While this may not seem real useful it does serve to show how to read the file and look for all of the elements:
Code For XmlTextReader
The code reads and prints all xml elements to a TextBox. This code is place in a button click event

 

 

protected void btnRead_Click(object sender, EventArgs e)
{
 
  string s = string.Empty;
   XmlTextReader xml = null;
  
  
try
  
{
      xml =
new XmlTextReader(Server.MapPath("~/App_Data/menu.xml"));
     
while (xml.Read())
      {
        
switch(xml.NodeType)
         {
       
    case XmlNodeType.Element:
               s =
String.Format("<{0}>", xml.Name);
               txtMenu.Text += s +
Environment.NewLine;
              
break;
           
case XmlNodeType.Text:
                txtMenu.Text += xml.Value +
Environment.NewLine;
                
break;
           
case XmlNodeType.CDATA:
                s =
String.Format("<!CDATA[{0}]>", xml.Value);
                txtMenu.Text += s +
Environment.NewLine;
               
break;
           
case XmlNodeType.Comment:
                s =
String.Format("<!--{0}-->", xml.Value);
                txtMenu.Text += s +
Environment.NewLine;
               
break;
           
case XmlNodeType.XmlDeclaration:
               
s =
String.Format("<?xml version='1.0'?>");
               
txtMenu.Text += s +
Environment.NewLine;
               
break;
            
case XmlNodeType.Document:
               
s =
String.Format("<!DOCTYPE {0} [{1}]", xml.Name, xml.Value);
                
txtMenu.Text += s +
Environment.NewLine;
               
break;
           
case XmlNodeType.EntityReference:
                
txtMenu.Text += xml.Name +
Environment.NewLine;
               
break;
           
case XmlNodeType.EndElement:
               
s =
String.Format("</{0}>", xml.Name);
               
txtMenu.Text += s +
Environment.NewLine;
               
break;
         
}

 

      }

    }
  

 

catch(Exception ex)
  
{
     
txtMenu.Text = ex.Message;
   
}
  
finally
  
{
     
if (xml != null)
        
xml.Close();
  
} 
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The code reads and prints all xml elements to a TextBox. This code is place in a button click event
Click the image below to see this code run
XmlTextReader
Running example of the XmlTextReader class. It displays the menu.xml file
Running example of the XmlTextReader class. It displays the menu.xml file

Using LINQ And XDocument


It used to be that if you wanted to do anything complex with XML you had to use an XmlDataDocument. While pretty flexible this object was a little cumbersome to use. Included in the release of the .NET framework version 3.5 was the new way of querying data called LINQ. LINQ along with XDocument allow you to query xml very similar to querying a database with SQL statements.

Linq is short for Language Integrated Query. If you are familar to using SQL to query databases, you will probably have and easy time with Linq, since they have many ideas in common.

LINQ will be covered in more detail later for now some simple examples of using it to display and search an xml file will be shown.

Using XDocument


 

 

To use LINQ and XDocument you must import

System.Xml.Linq

along with

System.Xml;

XDocument is the object that will hold the xml file that you want to use LINQ on. You create it very similar to the way you create XmlTextReader Object:

XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));

The difference is that with XDocument you call the Load method which loads the document into memory.

It gets even easier from here. Suppose you want to see all of the nodes that are within the menu. You simply use the Descendants method on the XDocument and specify that you want all of the nodes within Menu:

 

 

Simple LINQ Query
List all of the descendants of meny
List all of the descendants of meny

Working Example


Click the image below to see the code running:
Using Linq
Uses LINQ to display all nodes within the Menu Node
Uses LINQ to display all nodes within the Menu Node

Creating a Search Query With LINQ


Because LINQ works like sql you can build some pretty pwerful queries if need be. This next exmaple builds a query to search for a specific dish within the menu.xml file. Let's first take a look at the code example and then follow up with some explanation:

 

Using Linq To Search
This example searches for a particular dish within the menu.xml file.

protected void btnSearch_Click(object sender, EventArgs e)
{
  
string search = txtSearch.Text.Trim();

   XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));
   t
ry
  
{
     
var dish = from dishes in xml.Descendants("Dish")
        
where dishes.Element("Name").Value == search
        
select new
        
{
           
name = dishes.Element("Name").Value,
           
price = dishes.Element("Price").Value,
           
descript = dishes.Element("Description").Value
        
};

      foreach (var vals in dish)
     
{
        
txtMenu.Text += vals.name +
Environment.NewLine;
        
txtMenu.Text += vals.price +
Environment.NewLine;
        
txtMenu.Text += vals.descript +
Environment.NewLine;
      
}
  
}
  
catch (Exception ex)
  
{
     
txtMenu.Text = ex.Message;
  
}
 
}

}

 

 

 

This example searches for a particular dish within the menu.xml file.

Code Review


 

The first line of code within the function:

string search = txtSearch.Text.Trim();

gets the dish to be searche for from the txtSearch TextBox. It also trims all of the spaces which helps with removing any unwanted spaces the user may have accidentally put in.

XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));

Loads the xml document menu.xml

var dish = from dishes in xml.Descendants("Dish")

creates a variable called dish to hold the results of the query. The from dishes is another variable that will be used query all of the dishes in the xml file. It should be noted that these variables could be named anything. Since the search is for dishes this seemed appropriate.

What is important is that we are searching all of the descendants in the xml document called "Dish". This is important because it is the node we want to search for.

where dishes.Element("Name").Value == search

search where the element within dish has a value equal to what is being searched for. Remember, search is the value taken from the search TextBox.

select new
{
   name = dishes.Element("Name").Value,
   price = dishes.Element("Price").Value,
   descript = dishes.Element("Description").Value
};

Select new elements and store values from the node in variables name, price, descript. If you go back and look at the menu.xml file you will note the dish element contains sub elements Name, Price, and Description. These are the values we want to display.

foreach (var vals in dish)
{
   txtMenu.Text += vals.name + Environment.NewLine;
   txtMenu.Text += vals.price + Environment.NewLine;
   txtMenu.Text += vals.descript + Environment.NewLine;
}

The foreach loop iterates over the the collection from the query stored in dish. The information retrieved from the query is outpu to the TextBox. In this case there should only be one record returned from the query so the foeach loop should only run one time.

Running Code


You can see the code run by clicking the image below and pressing the search button. A value to search for has already been entered. But you can enter a dish if you would like. Here is a list of available dishes:

Mongololian Beef
Szechuan Spiced Beef
Chef's Special
Hot and Sour Pork
Mandarin Spareribs
Hunan Chicken
Lemon Fried Chicken
Kung Pao Chicken
Sweet and Sour Fish
Steamed Salmon with Black Bean Sauce
Mixed Seafood Delight
Spiced Oysters

 

Using LINQ To Search
Searches menu.xml for a particular dish and displays it's informaton in a TextBox
Searches menu.xml for a particular dish and displays it's informaton in a TextBox

Writing To XML Files


Using XDocument makes writing nodes to an XML file rather easy. You must first load the xml document, then do what I call "walk the tree" to get to the root of the node you want to add to. As an example suppose you want to add a new dish to the menu. The dish is

Name:House Special Beef
Price: 9.59
Description: Top quality beef marinated for tenderness

In xml this node will look like this:

<Dish>
   <Name>House Special Beef</Name>
   <Price>9.59</Price>
   <Description>Top quality beef marinated for tenderness</Description>
</Dish>

This new item needs to be added in the Beef category which is found within the meat category. To get there the tree needs to be traversed to that node. The path to be traversed is

Restaurant
   Menu
      Meat
         Beef

 

After Beef is where the new dish node needs to be added. The code to Accomplish this is as follows:

 

Add a new dish to menu.xml
This code adds the House Special Beef to menu.xml

 

 

protected void btnAdd_Click(object sender, EventArgs e)
{
   try
  
{
     
XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));
     
      xml.Root.Element(
"Menu").Element("Meat").Element("Beef").Add(
     
new XElement("Dish",
     
new XElement("Name", "House Special Beef"),
     
new XElement("Price", "9.59"),
     
new XElement("Description","Top quality beef marinated for tenderness" )));

      xml.Save(Server.MapPath("~
/App_Data/menu.xml"));

     
txtMenu.Text = "Data Saved Sucessfully";
   }
  
catch(Exception ex)
   {
      txtMenu.Text = ex.Message;
   }
}

 

 

 

 

 

 

 

This code adds the House Special Beef to menu.xml

Code Review


 

As with the other examples the first thing to do is open load the xml document:

XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));

The next step is to start at the root of the xml tree which is Restaurant in menu.xml. From the root the tree needs to be walked element by element until we get to the node to add the new dish to. Once there a new dish node can be added:

xml.Root.Element("Menu").Element("Meat").Element("Beef").Add(
new XElement("Dish",
new XElement("Name", "House Special Beef"),
new XElement("Price", "9.59"),
new XElement("Description","Top quality beef marinated for tenderness" )));

After Beef the new Dish node is added. Notice that the second argument to the XElement constructor is a new XElement up to the point all elements have been added.

Once the element has been created and added to the xml doc in memory, it must be saved back to the file:

xml.Save(Server.MapPath("~/App_Data/menu.xml"));

The example expands on this concept so that more dishes can be added. Having the ability to add House Special Beef more than once is really not exciting.

In this example a DropDown list has been added to select the meat, and TextBoxes have been aded to allow for adding the name, description, and price. Once you fill those out, press the add element button

Adding an Element
This example allows a new dish to be entered from the main form and added to menu.xml

 

 

protected void btnAdd_Click(object sender, EventArgs e)
{
  
string meat = ddlMeat.SelectedItem.Text;
  
string name = txtName.Text.Trim();
  
string Description = txtDescript.Text.Trim();
  
string price = txtPrice.Text.Trim();
  
   i
f (meat == string.Empty || Description == string.Empty || price == string.Empty)
   {
      txtMenu.Text =
"You must provide a meat, description, and price";
   }
  
else
  
{
     
try
     
{
        
XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));
         xml.Root.Element(
"Menu").Element("Meat").Element(meat).Add(
        
new XElement("Dish",
        
new XElement("Name", name),
        
new XElement("Price", price),
        
new XElement("Description", Description)));

         xml.Save(Server.MapPath(
"~/App_Data/menu.xml"));
         txtMenu.Text =
"Data Saved Sucessfully";
      }
     
catch (Exception ex)
      {
         txtMenu.Text = ex.Message;
      }
   }
}

 

 

 

 

This example allows a new dish to be entered from the main form and added to menu.xml

Running Example


Select the image below to see a demonstrtion of adding an element to an xml file.
Adding a value to menu.xml
Add a value to the menu
Add a value to the menu

Binding Data


 

ASP.NET has several controls that allow you to bind data to them. This means that you don't have to do anything but specify the data source to bind to and then bind the data.

If you look in the tool box under the Data catagory you will notice a list of controls that can be bound to a data source. The most popular of these and the one used in this demo is the GridView control. As you might suspect, this displays the data in row column fashion. The nice thing about this control is that it is very easy to change the way that it looks.

To start with a gridview control has been added to the form, this gridview control has been given the id of gvMenu because it is going to hold the menu information.:

 

Binding To The GridView


The most typical way to bind data is to fill a DataSet with data and then use that to bind the control.  The approach here is simpler and is going to involve using LINQ to query the data from the xml file. To start with the code that was used to search for a particular node will be used as a starting point. In this case the code can be simplified becuase there is no where clause. Basically, we want to bind all of the dishes to the GridView control:

 

Using Linq To Bind to the xml file
The DataSource of the GridView is set to the dish variable that holds the results from the query

private void bindReader()
{

   XDocument xml = XDocument.Load(Server.MapPath("~/App_Data/menu.xml"));
  
try
  
{
     
var dish = from dishes in xml.Descendants("Dish"
)
     
select
new
     
{
         name = dishes.Element(
"Name"
).Value,
         price = dishes.Element(
"Price"
).Value,
         description = dishes.Element(
"Description"
).Value
      };
      gvMenu.DataSource = dish;
      gvMenu.DataBind();
   }
  
catch (Exception
ex)
   {
   }
}

 

 

 

 

 

The DataSource of the GridView is set to the dish variable that holds the results from the query

The important lines of code are:

gvMenu.DataSource = dish;
gvMenu.DataBind();

The first line sets the data source of the GridView to be that of the variable dish which holds the results of the query.

The second line binds the data and fills the grid.

The running code looks like this:

Notice the column descriptions are the same ones used in the select new statement:

select new
{
name = dishes.Element("Name").Value,
price = dishes.Element("Price").Value,
description = dishes.Element("Description").Value
};

You can change these to anything you like or change the order around.

Adding Some Style to the GridView


 

The GridView has several build in attactive styles. You can also create your own custom styles as you have done for the skins.

To use one of the built in styles select the right facing arrow in the top right corner of the GridView:

From the menu that pops out select AutoFormat. From there select one of the styles that you like. In this example the Colorful style will be selected:

In the running example the variables from the select new statement have been rearranged to have the price last.

Running Exmaple


Click on the image below to see the code run:
Gridview data bound to the LINQ Query
The GridView control is data bound to the LINQ query
The GridView control is data bound to the LINQ query