Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ASP .NET Web Developer s Guide - Mesbah Ahmed, Chris Garrett

.pdf
Скачиваний:
37
Добавлен:
24.05.2014
Размер:
7.32 Mб
Скачать

360 Chapter 8 • Using XML in the .NET Framework

task, you will need to link your XML document to a particular schema first. Then you can test the validity of the XML document. To assign a schema to an XML document, perform the following steps:

1.Display the XML document in XML view (in the XML Designer).

2.Display its Property sheet. (It will be captioned DOCUMENT.)

3.Open the drop-down list box at the right-hand side of the targetSchema, and select the appropriate schema.

4.Now, go ahead and validate the document using the

XML>>Validate XML Data of the main menu.

By the way, there are many other third-party software packages that can also test if an XML document is well formed, and if it is valid (against a given schema). In this context, we have found the XML Authority (by TIBCO) and XML Writer (by Wattle Software) to be very good. An excellent tool named XSV is also available from www.w3.org/ 2000/09/webdata/xsv.

Structure of an XML Document

In an XML document, the data are stored in a hierarchical fashion. A hierarchy is also referred to as a tree in data structures. Conceptually, the data stored in the Catalog1.xml can be represented as a tree diagram, as shown in Figure 8.8. Please note that certain element names and values have been abbreviated in the tree diagram, mostly to conserve real estate on the page.

In this figure, each rectangle is a node in the tree. Depending on the context, a node can be of different types. For example, each product node in the figure is an element-type node. Each product node happens to be a child node of the catalog node.The catalog node can also be termed as the parent of all product nodes.

Each product node, in turn, is the parent of its PId, PName, and Price nodes. In this particular tree diagram, the bottom-most nodes are not of element-

type; rather, these are of text-type.There could have been nodes for each attribute and its value, too, although we have not shown those in this diagram.

The Product nodes are the immediate descendants of the Catalog node. Both Product nodes are siblings of each other. Similarly, the PId, PName, and Price nodes under a specific product node are also siblings of each other. In short, all children of a parent are called siblings.

www.syngress.com

Using XML in the .NET Framework • Chapter 8

361

At this stage, you may have been wondering why we are studying the family history rather than ASP.Well, you will find out pretty soon that all of these terminologies will play major roles in taming the beauties and the beasts of something called XML technology.

Figure 8.8 The Tree-Diagram for Catalog1.xml

 

 

 

 

The Root: Also Known As:

 

First Child of Catalog

 

 

 

Document.Element

 

 

 

 

 

 

 

 

 

Catalog

 

 

 

Product

 

 

Product

Siblings

A Text-Type Node

 

 

 

 

 

 

 

 

PId

PName

Price

PId

PName

Price

F10

Shimano

47.76

F20

Bantam

49.99

Processing XML Documents Using .NET

The entire ADO.NET Framework has been designed based on XML technology. Many of the ADO.NET data-handling methodologies, including DataTables and DataSets, use XML in the background, thus keeping it transparent to us.The

.NET Framework’s System.Xml namespace provides a very rich collection of classes that can be used to store and process XML documents.These classes are also often referred to as the XML.NET.

Before we get into the details of the XML.NET objects, let us ask ourselves several questions. As ASP NET developers, what kind of support would we need from .NET for processing XML documents? Well, at the very least, we would like .NET to assist us in creating, reading, and parsing XML documents. Anything else? Okay, if we have adequate cache, we would like to load the entire document in the memory and process it directly from there. If we do not have enough cache, then we would like to read various fragments of an XML document one piece at a time. Do we want more? How about the ability for searching and querying the information contained in an XML document? How about instantly creating an XML document from a database query and sending it to our B2B partners? How about converting an XML document from one format to another

www.syngress.com

362 Chapter 8 • Using XML in the .NET Framework

format and transmitting it to other servers? Actually, XML.NET provides all of these, and much more! All of the above questions fall into two major categories:

1.How do we read, parse and write XML documents?

2.How do we store, structure, and process them in the memory?

As mentioned earlier, XML is associated with a growing family of technologies and frameworks.The major trends in this area are W3C DOM, XSLT, XPath, XPath Query, SAX, and XSLT. In XML.NET, Microsoft has incorporated almost all of these frameworks and technologies. It has also added some of its own unique ideas.There is a plethora of alternative XML.NET objects to satisfy our needs and likings. However, it’s a jungle out there! In the remainder of this section, we will have a brief glance over this jungle.

Migrating…

Legacy Systems and XML

Organizational data stored in legacy systems can be converted to appropriate XML documents, if needed, reasonably easily. There is third-party software like XML Authority by Tibco Extensibility and others, which can convert legacy system’s data into XML format. We can also use VS.NET to convert legacy data to XML documents.

Reading and Writing XML Documents

Two primary classes in this group are XmlReader and XmlWriter. Both of these classes are abstract classes, and therefore we cannot create objects of these classes. Microsoft has provided a number of concrete implementations of both of these classes:

XmlTextReader We may use an object of this class to read noncached XML data on a forward-only basis. It checks for well-formed XML, but it does not support data validation.

XmlNodeReader An object of this class can be used to access noncached forward-only data from an XML node. It does not support data validation.

www.syngress.com

Using XML in the .NET Framework • Chapter 8

363

XmlValidationReader This is very similar to the XMLTextReader, except that it accommodates XML data validation.

We may create objects of these classes and use their methods and properties. If warranted, we may also extend these classes to provide further specific functionalities. Fortunately, the XmlWriter class has only one concrete implementation: XmlTextWriter. It can be used to write XML document on a forward-only basis. These classes and their relationships are shown in Figure 8.9.

Figure 8.9 Major XmlReader and XmlWriter Classes

XmlTextReader

XmlReader

XmlNodeReader

XmlValidatingReader

XmlWriter

XmlTextWriter

Storing and Processing XML Documents

Once XML data are read, we need to structure these data in the computer’s memory. For this purpose, the major offerings include the XmlNode class and the XPathDocument class.The XmlNode class is an abstract class.There are a number of concrete implementations of this class, too, such as the XmlDocument, XmlAttribute, XmlDocumentFragment, and so on. We will limit our attention to the XmlDocument class, and to one of its subsequent extensions named the XmlDataDocument.The characteristics of some of these classes are as follows:

XmlDocument This class structures an XML document according to a DOM tree (as specified in the W3C DOM Core Level 1 and 2 specifications).

XmlDataDocument This class is a major milestone in integrating XML and database processing. It allows two views of the in-cache data: the Relational Table view, and the XML Tree View.

www.syngress.com

364 Chapter 8 • Using XML in the .NET Framework

XPathDocument This class employs the XSLT and XPath technologies, and enables you to transform an XML document in to a desired format.

Above classes are essentially used for storing the XML data in the cache. Just storing data in the memory serves us no purpose unless we can process and query these data.The .NET Framework has included a number of classes to operate on the cached XML data.These classes include XPathNavigator, XPathNodeIterator, XSLTransform, XmlNodeList, etc.These classes are shown in Figure 8.10.

Figure 8.10 Major XML Classes for In-Memory Storage and Processing

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

XmlNode

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Navigation and Other

 

 

 

 

 

 

 

 

 

 

 

Related Processing

 

 

XmlDocument

 

 

XmlAttribute

 

 

Classes

 

 

 

 

 

 

 

 

 

 

 

and more ...

 

 

 

 

 

 

 

 

 

 

 

XPathNavigator

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

XPathNodeIterator

 

 

 

 

 

 

 

 

 

 

XSLTransform

 

 

 

 

 

 

 

 

 

 

 

 

XmlDataDocument

 

 

XPathDocument

 

XmlNodeList

 

 

 

 

 

many more ...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Reading and Parsing Using

the XmlTextReader Class

The XmlTextReader class provides a fast forward-only cursor that can be used to “pull” data from an XML document. An instance of it can be created as follows:

Dim myRdr As New XmlTextReader(Server.MapPath("catalog2.xml"))

Once an instance is created, the imaginary cursor is set at the top of the document.We may use its Read() method to extract fragments of data sequentially. Each fragment of data is distantly similar to a node of the underlying XML tree.The NodeType property captures the type of the data fragment read, the Name property contains the name of the node, and the Value property contains the value of the node, if any.Thus, once a data fragment has been read, we may use the following type of statement to display the node-type, name, and value of the node.

Response.Write(myRdr.NodeType.ToString() + " " +

myRdr.Name + ": " + myRdr.Value)

www.syngress.com

Using XML in the .NET Framework • Chapter 8

365

The attributes are treated slightly differently in the XmlTextReader object.When a node is read, we may use the HasAttributes property of the reader object to see if there are any attributes attached to it. If there are attributes in an element, the MoveToAttribute(i) method can be applied to iterate through the attribute collection. The AttributeCount property contains the number of attributes of the current element. Once we process all of the attributes, we need to apply the MoveToElement method to move the cursor back to the current element node.Therefore, the following code will display the attributes of an element:

If myRdr.HasAttributes Then

For i = 0 To myRdr.AttributeCount - 1

myRdr.MoveToAttribute(i)

Response.Write(myRdr.NodeType.ToString() + " : "+ myRdr.Name _

+ ": " + myRdr.Value + "</br>")

Next i

myRdr.MoveToElement()

End If

Microsoft has loaded the XmlDocument class with a variety of convenient class members. Some of the frequently used methods and properties are AttributeCount,

Depth, EOF, HasAttributes, HasValue, IsDefault, IsEmptyElement, Item, ReadState, and Value.

Parsing an XML Document:

In this section, we will apply the XMLTextReader object to parse and display all data contained in our Catalog2.xml (as shown in Figure 8.5) document.The code for this example and its output are shown in Figures 8.11 and 8.12, respectively. The code shown in Figure 8.12 is available in the accompanying CD. Our objective is to start at the top of the document and then sequentially travel through its nodes using the XMLTextReader’s Read() method.When there is no more data to read, the Read() method returns “false.”Thus, we are able to build the While myRdr.Read() loop to process all data. Please review the code (Figure 8.12) and its output cautiously.While displaying the data, we have separated the node-type, node-name, and values using colons. Not all elements have names or values. Hence, you will see many empty names and values after respective colons.

www.syngress.com

366 Chapter 8 • Using XML in the .NET Framework

Figure 8.11 Truncated Output of the XmlTextReader1.aspx Code

Figure 8.12 XmlTextReader1.aspx

<!— Chapter8\xmlTextReader1.aspx —>

<%@ Page Language = "VB" Debug ="True" %> <%@ Import Namespace="System.Xml" %> <Script runat="server">

Sub Page_Load(sender As Object, e As EventArgs)

Dim myRdr As New XmlTextReader(Server.MapPath("Catalog2.xml"))

Dim i As Integer

While myRdr.Read()

Response.Write(myRdr.NodeType.ToString() + " : " + myRdr.Name _ + ": " + myRdr.Value + "<br/>")

If myRdr.HasAttributes Then

For i = 0 To myRdr.AttributeCount - 1 myRdr.MoveToAttribute(i)

Response.Write(myRdr.NodeType.ToString() + " : "+ myRdr.Name _ + ": " + myRdr.Value + "</br>")

Next i myRdr.MoveToElement()

Continued

www.syngress.com

Using XML in the .NET Framework • Chapter 8

367

Figure 8.12 Continued

End If

End While

myRdr.Close()

End Sub

</Script>

Navigating through an XML

Document to Retrieve Data

In the previous section, we extracted and displayed all data, including the “whitespaces” contained in an XML document. Now, we will illustrate an example where we will navigate through the document and pick up only those data that are necessary for an application.The output of this application is shown in Figure 8.13. In this example, we will display the names of our products in a list box.We will load the list box using the Product Name data from the XML file.The user will select a particular product. Subsequently, we will search the XML document to find and display the price of the product.We will travel through the XML file twice, once to load the list box, and once to find the price of a selected product. Please be aware that we could have easily developed the application by building an array or arraylist of the products during the first pass through the XML data, thus avoiding a second pass. Nevertheless, we are reading the file twice just to illustrate various methods and properties of the XmlTextReader object.

Figure 8.13 Output of the Navigation ASPX Example XmlTextReader2.aspx

www.syngress.com

368 Chapter 8 • Using XML in the .NET Framework

To load the List Box, we will go through the following process:We will load the list box in the Page_Load event. Here, we will read the nodes one at a time. If the node type is of element-type, we will check if its name is ProductName. If it is a ProductName node, we will perform a Read() to get to its text node and then apply the myRdr.ReadString() method to extract the value and load it in the list box. Finally, we will close the reader object. Caution: We are assuming that there is no “whitespace” between the ProductName and its Text node. If there is a “whitespace,” we will need to put the second Read() in a loop until the nodetype is Text.

While myRdr.Read()

If XmlNodeType.Element

If myRdr.Name="ProductName" Then

myRdr.Read()

lstProducts.Items.Add(myRdr.ReadString) End If

End If

End While myRdr.Close()

To find the price of the selected product, we will go through the following process:We will include the necessary code in the “unclick” event code of the command button “Show Price.”We will create a second XmlTextReader object based on the catalog2.xml file. Of course, we may scan all nodes sequentially to find the price. However, the XmlTextReader class enables you to skip undesirable nodes, such as the “whitespace” or the declaration nodes via the MoveToContent() method. According to Microsoft, all nonwhitespace, Element, End Element, EntityReference, and EndEntity nodes are content nodes.The MoveToContent() method checks whether the current node is a content node. If the node is not a content node, then the method skips to the next content node.You need to be careful though. If the current node happens to be a content node, the cursor does not move to the next content node automatically on a further MoveToContent().

Initially, when we instantiate the reader object, its node type is None. It happens to be a noncontent node. Hence our first MoveToContent() statement takes us to a content node.There, we check if it is an Element-type node named “ProductName” and if its ReadString() is equal to the name of the selected product. If all are true, then we apply a Read() to go to the next node.This Read() may take us to a “whitespace” node, and thus we have applied a MoveToContent()

www.syngress.com

Using XML in the .NET Framework • Chapter 8

369

to get to the ListPrice node. Figure 8.14 shows an excerpt of the relevant code. The complete code is available in XmlTextReader2.aspx file in the CD.

Figure 8.14 Excerpt of XmlTextReader2.aspx

Sub showPrice(s As Object, e As EventArgs)

Dim myRdr2 As New XmlTextReader(Server.MapPath("Catalog2.xml")) Dim unitPrice As Double

Dim qty AS Integer

Do While Not myRdr2.EOF()

If (myRdr2.MoveToContent() = XmlNodeType.Element _

And myRdr2.Name ="ProductName" _

And myRdr2.ReadString()=lstProducts.SelectedItem.ToString())

myRdr2.Read()

If (myRdr2.MoveToContent() = XmlNodeType.Element _

And myRdr2.Name ="ListPrice")

unitPrice=Double.Parse(myRdr2.ReadString())

lblPrice.Text= "Unit Price = " + FormatCurrency(unitPrice)

Exit Do

End If

End If

myRdr2.Read()

Loop

qty = Integer.Parse(txtQty.Text)

lblAmount.Text = "Amount Due = " + FormatCurrency(qty * unitPrice) myRdr2.Close()

End Sub

By the way, we could have also used the MoveToContent() method to load our list box more effectively. However, we just wanted to show the alternative methodologies.

NOTE

We may also read XML files from remote servers as follows:

Dim myRdr As New XmlTextReader("http://ahmed2/Chapter8/

Catalog2.xml")

www.syngress.com