Accessing XML with ASP.NET

IOTA^_^    

Sams Teach Yourself ASP.NET in 21 Days, Second Edition
By Chris Payne
Table of Contents
Day 11.  Using XML in ASP.NET


Accessing XML is very similar to accessing a database with ADO.NET. The .NET Framework provides a lot of objects that give you varying degrees of control over the data, each with its own advantages and drawbacks. This section will look at the two simplest objects: the XmlTextReader and the XmlTextWriter in the System.XML namespace.

Reading XML

The XmlTextReader provides a simple, fast mechanism for accessing the raw contents of an XML file. This object is similar to an OleDbDataReader in that it provides forward-only access, without a lot of the overhead that the DataSet requires.

To open an XML file, simply create a new XmlTextReader and pass it the filename of the XML file. If you create the ASP.NET file XMLReader.aspx and put it in the same directory as your XML file, you could simply use the following:

 'VB.NET Dim reader As new XmlTextReader(file name with path) //C# XmlTextReader reader = new XmlTextReader(file name with path); 

There are no connection strings to worry about. The full pathname is necessary, however. This can be produced by the Server.MapPath method. (See Day 4, "Using ASP.NET Objects with C# and VB.NET.") To access the data, you use the Read method, which is similar to the OleDbDataReader. For example:

 Do While (reader.Read())    ' Do some work on the data Loop 

The Read method advances through the XML file automatically whenever it's called. Listing 11.3 presents an ASP.NET Web page that reads and displays the contents of the books.xml file using the XmlTextReader class.

Listing 11.3 Accessing XML Data with XmlTextReader
 1:    <%@ Page Language="VB" %> 2:    <%@ Import Namespace="System.Xml" %> 3: 4:    <script runat=server> 5:       sub Page_Load(Sender as Object, e as EventArgs) 6:          dim reader as XmlTextReader 7: 8:          try 9:             reader = new XmlTextReader(Server.MapPath _ 10:                ("books.xml")) 11:             While reader.Read() 12:                Response.Write("<b>" & reader.Name & "</b> " & _ 13:                   reader.Value & "<br>") 14:             End While 15:          catch ex as Exception 16:             Response.Write("Error accessing XML file") 17:          finally 18:             reader.Close 19:         end try 20:    end sub 21:    </script> 22: 23:    <html><body> 24: 25:    </body></html> 

graphics/analysis_icon.gif

The first new thing to note is the Import statement on line 2, which imports the System.Xml namespace. This Import statement allows you to work with the XML-related classes, such as XmlTextReader.

Next, you declare your XmlTextReader on line 6. You then wrap the code that will access the XML in a try block. (Remember that whenever you access resources outside ASP.NET, you should use a try statement.) On line 9, you open the reader with your XML file. This syntax requires that you specify the entire path to the XML file, so use Server.MapPath to return that information. Specifically, Server.MapPath will return c:\inetpub\wwwroot\tyaspnet21days\day11\books.xml.

Finally, use the Read method to loop through the XML contents automatically and display each item's Name and Value in the browser. Don't forget to close the reader, as shown in the finally block on lines 17 and 18. Figure 11.3 contains a screenshot of Listing 11.3 when viewed through a browser.

Figure 11.3. Displaying the contents of books.xml.

graphics/11fig03.gif

Figure 11.3 shows all of the tags in your XML file, including opening and closing tags not exactly what you wanted. Unfortunately, the XmlTextReader object provides very limited functionality. It doesn't care what tags it returns, so it just returns all of them!

To combat this, the XmlTextReader has a NodeType property that tells you what kind of data you're looking at. Table 11.1 lists some of the most common node types available.

Table 11.1. NodeTypes for the XmlTextReader
Type Description
Attribute An attribute
CDATA This section escapes text that would otherwise be recognized as a markup language, such as HTML
Comment Comments delimited by <!-- and --> tags
Document The root of the XML data tree
Element An element, typically the actual data in an XML file
None You're not examining a node
Text Returns the text content of an element
XMLDeclaration The XML declaration node, such as <?XML version='1.0'?>

Let's use these NodeTypes and modify Listing 11.3 to return only the data you're interested in.

Listing 11.4 Using NodeTypes to Return Data
 1:    <%@ Page Language="VB" %> 2:    <%@ Import Namespace="System.Xml" %> 3: 4:    <script runat=server> 5:       sub Page_Load(Sender as Object, e as EventArgs) 6:          dim reader as XmlTextReader 7:          dim i as integer 8: 9:          try 10:             reader = new XmlTextReader(Server.MapPath _ 11:                ("books.xml")) 12:             While reader.Read() 13:                Select Case reader.NodeType 14:                   Case XMLNodeType.Element 15:                      if reader.HasAttributes then 16:                         for i = 0 to reader.AttributeCount - 1 17:                            Response.Write(reader.GetAttribute _ 18:                               & " ") 19:                         next 20:                         Response.Write("<br>") 21:                      end if 22:                   Case XMLNodeType.Text 23:                      Response.Write(reader.Value & "<br>") 24:                End Select 25:             End While 26:          catch ex as Exception 27:             Response.Write("Error accessing XML file") 28:          finally 29:             reader.Close 30:          end try 31:       end sub 32:    </script> 33: 34:    <html><body> 35: 36:    </body></html> 

graphics/analysis_icon.gif

You inserted a case statement on line 13 to evaluate the type of node before you output anything. The first case, on line 14, executes if the reader object's NodeType is an Element. If the node has any attributes, you loop through them and use the GetAttribute method to return the corresponding value. On line 23, you simply output the value if the node is a text item. Figure 11.4 shows the output of this new code listing.

Figure 11.4. Displaying the contents of books.xml using NodeTypes.

graphics/11fig04.gif

This produces a better representation of the data.

If you know the specific structure of the XML file, such as the names of the elements and their attributes, you can customize your code further so that only the items you're interested in are displayed. For example, if you only want to see the genre attribute, you can write the following in place of the attribute loop on lines 13 24:

 Response.Write(reader.Item("genre") & "<br>") 

Writing XML

The XmlTextWriter object makes it just as easy to write XML files as XmlTextReader makes it to read them. This object provides Write methods that produce the appropriate output.

For example, Listing 11.5 creates a new XML file and places an entry in it.

Listing 11.5 Writing XML Files Using XmlTextWriter
 1:    <%@ Page Language="VB" %> 2:    <%@ Import Namespace="System.Xml" %> 3: 4:    <script runat=server> 5:       sub Page_Load(Sender as Object, e as EventArgs) 6:          dim writer as XmlTextWriter 7: 8:          try 9:             writer = new XmlTextWriter(Server.MapPath _ 10:                ("books2.xml"), nothing) 11: 12:             writer.WriteStartDocument 13:             writer.Formatting = Formatting.Indented 14:             writer.Indentation = 3 15:             writer.WriteStartElement("bookstore") 16:                writer.WriteStartElement("book") 17:                   writer.WriteAttributeString("genre", "history") 18:                   writer.WriteAttributeString("style", "hardcover") 19: 20:                   writer.WriteElementString("title", "Vietnam") 21: 22:                   writer.WriteElementString("price", _ 23:                      "6.99") 24: 25:                   writer.WriteStartElement("author") 26:                      writer.WriteElementString("first-name", _ 27:                         "Michael") 28:                      writer.WriteElementString("last-name", _ 29:                         "Avery") 30:                   writer.WriteEndElement() 31:                writer.WriteEndElement() 32:             writer.WriteEndElement() 33: 34:             writer.Flush 35:          catch ex as Exception 36:             Response.Write("Error accessing XML file") 37:          finally 38:             writer.Close 39:             Response.Write("Finished processing") 40:          end try 41:       end sub 42:    </script> 43: 44:    <html><body> 45: 46:    </body></html> 

graphics/analysis_icon.gif

The structure of this listing is similar to that for the XmlTextReader. You declare your writer on line 6 and wrap everything else in a try block. You then instantiate your writer on line 9. The first parameter is the name of the XML file to write to, the second parameter is the encoding (the default is UTF-8). If there's no file with this name, ASP.NET will create one. Otherwise, it uses the existing file.

Caution

Creating an XML file in this way will overwrite any file with the same name. In this case, existing content in books2.xml will be lost. So make sure you're not overwriting anything important!


Line 12 writes the XML declaration tag to the file, <?XML version='1.0'?>. This is part of a well-formed XML document. Lines 13 and 14 specify how you want the outputted XML to look. On line 13, you tell ASP.NET to indent the file, and on line 14, you tell it to use three spaces to do so. This makes reading the file later much easier on the eyes. The Formatting property can be set to Indented or None. You can use the IndentChar property to set the character used for indenting.

Line 15 starts the data generation. You use the WriteStartElement and WriteEndElement methods to open and close element tags. Line 15 produces the tag <bookstore>, and line 32 produces the corresponding closing tag, </bookstore>. Line 16 opens the <book> tag, and line 31 closes it.

On lines 17 and 18, you create the attributes for the <book> tag, genre and style, and assign the values accordingly. WriteElementString encapsulates the start and end element functionality for simple elements. Here's line 20:

 writer.WriteElementString("title", "Vietnam") 

It produces the following output:

 <title>Vietnam</title> 

In essence, WriteElementString produces the opening and closing tags specified by the first parameter, and it inserts the string value specified by the second parameter.

After closing all the opened tags, you flush the content on line 34. This is similar to flushing the response buffer (see Day 5, "Beginning Web Forms"), except that the content is written to a file instead of the browser. Finally, you close the writer on line 38.

Note

Normally, calling the Close method will output the XML. Calling Flush isn't necessary unless the writer needs to be reused for other output.

Calling the Close method also closes any open element and attribute tags, although it's highly recommended that you remember to do so manually.


Figure 11.5 shows the XML output file.

Figure 11.5. The books2.xml output from Listing 11.5.

graphics/11fig05.gif

Validating XML

XML must be well-formed after all, it's supposed to be a universal data representation language. If XML is not well-formed, achieving this standard becomes very difficult. Imagine two companies trying to share an XML data file. A file that's not well-formed leaves data open to interpretation, which could lead to disastrous results if both companies interpret it differently.

ASP.NET allows you to validate XML against a schema. To do so, you create a new object, the XmlValidatingReader, and specify the type of validation you want to use:

 'create reader here dim validator as new XMLValidatingReader(reader) 'DTD schema validator.ValidationType = ValidationType.DTD 'XDR schema validator.ValidationType = ValidationType.XDR 'XSD schema validator.ValidationType = ValidationType.Schema 'let ASP.NET choose automatically validator.ValidationType = ValidationType.Auto 

Then you add an event handler for the validation routine, which will use the schema specified in the XML document. You'll be using XDR validation here. Like you did with books.xml, modify the bookstore element in books2.xml to read as follows:

 <bookstore xmlns="x-schema:books.xdr"> 

This tells ASP.NET that you'll use the schema described in books.xdr (in Listing 11.2) to validate your file. If the XML file is valid and follows the schema, you shouldn't notice any difference and the output should be the same as before.

Listing 11.6 shows the beginning of an example (continued in Listing 11.7).

Listing 11.6 Validating XML in C#
 1:    <%@ Page Language="C#" %> 2:    <%@ Import Namespace="System.Xml" %> 3:    <%@ Import Namespace="System.Xml.Schema" %> 4: 5:    <script runat="server"> 6:       private XmlTextReader reader; 7:       private XmlValidatingReader validator; 8: 9:       void Page_Load(Object Sender, EventArgs e) { 10:          try { 11:             reader = new XmlTextReader(Server.MapPath ("books2.xml")); 12:             validator = new XmlValidatingReader(reader); 13:             validator.ValidationType = ValidationType.XDR; 14: 15:             validator.ValidationEventHandler += new ValidationEventHandler(this. graphics/ccc.gifShowError); 16: 17:             while (validator.Read()) { 18:                //do nothing; 19:             } 20:          } catch (Exception ex) { 21:             Response.Write("Error accessing XML file"); 22:          } finally { 23:             reader.Close(); 24:          } 25:    } 

graphics/analysis_icon.gif

This listing looks somewhat similar to all your other listings. Note the additional namespace System.Xml.Schema on line 3. You'll need this to validate against your schema information. You start validating by creating an XmlTextReader (line 6) and opening your XML file, books2.xml (line 11). Next you instantiate your XmlValidatingReader on line 12 by supplying it the XmlTextReader object. This is so your validating reader will know which XML data file to validate. On line 13, you specify that you want to use the XDR schema defined in your XML file to validate the data.

Most built-in events in ASP.NET have a predefined event handler (the Page_Load method for the Page object's Load event, for instance). The validation event doesn't, however, so you have to define one using the syntax on line 15 (or the AddHandler method for VB.NET):

 AddHandler validator.ValidationEventHandler, new ValidationEventHandler(addressof  graphics/ccc.gifShowError) 

Essentially, this code assigns an event handler to the event in question ValidationEventHandler in this case. The ShowError method will be executed whenever this event fires. This method can be named anything you want. You don't need to worry too much about the details behind this mechanism, but it's useful to know the syntax if you ever need to use it.

Also note the empty while loop on lines 17 19. Normally you could read the data and output whatever you like here, but for our purposes of validation here, you don't need to. You only want to read the data to verify it, not to display it.

The ShowError function, which makes up the remainder of your ASP.NET Web page, can be found in Listing 11.7.

Listing 11.7 The ShowError Function
 26:       void ShowError(Object Sender, ValidationEventArgs e) { 27:          Response.Write("<font color=\"red\">" + e.Message + "<br>"); 28: 29:          if (reader.LineNumber > 0) { 30:             Response.Write("Line: " + reader.LineNumber + " Position: " + reader. graphics/ccc.gifLinePosition + "</font><p>"); 31:          } 32:       } 33:    </script> 34: 35:    <html><body> 36: 37:    </body></html> 

graphics/analysis_icon.gif

Here you define the ShowError function that's called whenever something in the XML file fails the validation. Note the ValidationEventArgs parameter in the method declaration. This parameter contains a Message property that contains a user-friendly description of any errors that occur. Thus, on line 30, you output this description to the browser in a red font. You use the LineNumber and LinePosition properties of the XmlValidatingReader to display the location of the error in the XML file. This is very useful for tracking down problems.

Note

You may have noticed in Listing 11.6 that you moved the declaration of the XmlTextReader outside the Load event. This allows you to use this object from any method within the page, rather than simply within the Page Load event. This is why you can use it from the ShowError method.

Had you left the declaration in the PageLoad event, accessing the reader from the ShowError function would produce an error.


If the format of your books2.xml file looks exactly like books.xml (and it should), you shouldn't receive any errors and everything should work as planned. However, let's modify the XML a bit so you can see validation at work. See Listing 11.8.

Listing 11.8 Books2.xml A Non-Valid XML File
 1:    <?xml version="1.0"?> 2:    <bookstore xmlns="x-schema:books.xdr"> 3:       <book genre="history"> 4:          <title>Vietnam</title> 5:          <price>hello!</price> 6:          <author> 7:             <first-name>Michael</first-name> 8:             <last-name>Avery</last-name> 9:          </author> 10:       </book> 11:    </bookstore> 

According to your schema, books.xdr, this file has two errors it omits the style attribute in the book element, and it uses a string in the price attribute. Figure 11.6 shows the error messages you get when viewing the output of the validation code (Listings 11.6 and 11.7) through a Web browser.

Figure 11.6. Errors in validation.

graphics/11fig06.gif

If you had used the while loop in Listing 11.6 to output any data, that data would have appeared in Figure 11.6 along with the error messages.


    IOTA^_^    
    Top


    Sams Teach Yourself ASP. NET in 21 Days
    Sams Teach Yourself ASP.NET in 21 Days (2nd Edition)
    ISBN: 0672324458
    EAN: 2147483647
    Year: 2003
    Pages: 307
    Authors: Chris Payne

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net