1. Trang chủ
  2. » Công Nghệ Thông Tin

Professional ASP.NET 3.5 in C# and Visual Basic Part 58 pdf

10 438 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 295,74 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

> 10.00]]/b:price", namespaceMgr Dim price As Decimal = _ CTypenode.ValueAsGetTypeDecimal, Decimal Response.WriteString.Format"Price is {0}", _ price Next C# //Load document string books

Trang 1

namespaceMgr.AddNamespace("b", "http://example.books.com")

’All books whose price is not greater than 10.00

For Each node As XPathNavigator In nav.Select( _

"//b:book[not(b:price[ > 10.00])]/b:price", namespaceMgr)

Dim price As Decimal = _

CType(node.ValueAs(GetType(Decimal)), Decimal)

Response.Write(String.Format("Price is {0}<BR/>", _

price))

Next

C#

//Load document

string booksFile = Server.MapPath("books.xml");

XPathDocument document = new XPathDocument(booksFile);

XPathNavigator nav = document.CreateNavigator();

//Add a namespace prefix that can be used in the XPath expression

XmlNamespaceManager namespaceMgr = new XmlNamespaceManager(nav.NameTable);

namespaceMgr.AddNamespace("b", "http://example.books.com");

//All books whose price is not greater than 10.00

foreach(XPathNavigator node in

nav.Select("//b:book[not(b:price[ > 10.00])]/b:price",

namespaceMgr))

{

Decimal price = (decimal)node.ValueAs(typeof(decimal));

Response.Write(String.Format("Price is {0}<BR/>",

price));

}

If you then want to modify the underlying XML nodes, in the form of anXPathNavigator, you would

use an XmlDocument instead of an XPathDocument Your XPath expression evaluation may slow you

down, but you will gain the capability to edit Beware of this tradeoff in performance Most often,

you will want to use the read-only XPathDocument whenever possible Listing 10-13 illustrates this

change with the new or changed portions appearing in gray Additionally, now that the document is

editable, the price is increased 20 percent

Listing 10-13: Querying and editing XML with XmlDocument and XPathNodeIterator

VB

’Load document

Dim booksFile As String = Server.MapPath("books.xml")

Dim document As New XmlDocument()

document.Load(booksFile)

Dim nav As XPathNavigator = document.CreateNavigator()

’Add a namespace prefix that can be used in the XPath expression

Dim namespaceMgr As New XmlNamespaceManager(nav.NameTable)

namespaceMgr.AddNamespace("b", "http://example.books.com")

’All books whose price is not greater than 10.00

For Each node As XPathNavigator In nav.Select( _

Trang 2

"//b:book[not(b:price[ > 10.00])]/b:price", namespaceMgr) Dim price As Decimal = CType(node.ValueAs(GetType(Decimal)), Decimal)

node.SetTypedValue(price * CDec(1.2))

Response.Write(String.Format("Price raised from {0} to {1}<BR/>", _

price, _ CType(node.ValueAs(GetType(Decimal)), Decimal))) Next

C#

//Load document

string booksFile = Server.MapPath("books.xml");

XmlDocument document = new XmlDocument();

document.Load(booksFile);

XPathNavigator nav = document.CreateNavigator();

//Add a namespace prefix that can be used in the XPath expression

XmlNamespaceManager namespaceMgr = new XmlNamespaceManager(nav.NameTable);

namespaceMgr.AddNamespace("b", "http://example.books.com");

//All books whose price is not greater than 10.00

foreach(XPathNavigator node in

nav.Select("//b:book[not(b:price[ > 10.00])]/b:price",

namespaceMgr))

{

Decimal price = (decimal)node.ValueAs(typeof(decimal));

node.SetTypedValue(price * 1.2M);

Response.Write(String.Format("Price inflated raised from {0} to {1}<BR/>",

price, node.ValueAs(typeof(decimal))));

}

Listing 10-13 changes theXPathDocumentto anXmlDocument, and adds a call toXPathNavigator

.SetTypedValueto update the price of the document in memory The resulting document could then

be persisted to storage as needed IfSetTypedValuewas instead called on theXPathNavigatorthat was

returned byXPathDocument, aNotSupportedExceptionwould be thrown as theXPathDocument

is read-only

TheBooks.xmldocument loaded from disk useshttp://example.books.comas its default namespace

Because theBooks.xsdXML Schema is associated with theBooks.xmldocument, and it assigns the

default namespace to behttp://example.books.com, the XPath must know how to resolve that

names-pace Otherwise, you cannot determine if an XPath expression with the wordbookin it refers to a book

from this namespace or another book entirely AnXmlNamespaceManageris created, andbis arbitrarily

used as the namespace prefix for the XPath expression

Namespace resolution can be very confusing because it is easy to assume that your XML file is all alone

in the world and that specifying a node namedbookis specific enough to enable the system to find it

However, remember that your XML documents should be thought of as living among all the XML in the

world — this makes providing a qualified namespace all the more important TheXmlNamespaceManager

in Listing 10-12 is passed into the call toSelectNodesin order to associate the prefix with the appropriate

namespace Remember, the namespace is unique, not the prefix; the prefix is simply a convenience acting

as an alias to the longer namespace If you find that you’re having trouble getting an XPath expression to

Trang 3

work and no nodes are being returned, find out if your source XML has a namespace specified and that

it matches up with a namespace in your XPath

Using XPath with XDocuments in LINQ for XML

You can use XPath against anXDocumentobject by adding a reference to theSystem.Xml.XPath

namespace via a using or Imports statement Adding this reference adds new extension methods to the

XDocumentlikeCreateNavigatorget to anXPathNavigatorand the very useful XPathSelectElements

XPathSelectElements is similar to theSelectNodesandSelectSingleNodemethods of theSystem.Xml

.XmlDocument These extension methods are part of the ‘‘bridge classes’’ that provide smooth integration betweenSystem.XmlandSystem.Xml.Linq

Listing 10-12q: Querying XDocuments with XPath Expressions

VB

Dim booksFile As String = Server.MapPath("books.xml")

Dim document As XDocument = XDocument.Load(booksFile)

’Add a namespace prefix that can be used in the XPath expression

Dim namespaceMgr As New XmlNamespaceManager(New NameTable())

namespaceMgr.AddNamespace("b", "http://example.books.com")

’All books whose price is not greater than 10.00

Dim nodes = document.XPathSelectElements(

"//b:book[not(b:price[ > 10.00])]/b:price", namespaceMgr)

For Each node In nodes

Response.Write(node.Value + "<BR/>")

Next

C#

//Load document

string booksFile = Server.MapPath("books.xml");

XDocument document = XDocument.Load(booksFile);

//Add a namespace prefix that can be used in the XPath expression

// Note the need for a NameTable It could be new or come from elsewhere

XmlNamespaceManager namespaceMgr = new XmlNamespaceManager(new NameTable());

namespaceMgr.AddNamespace("b", "http://example.books.com");

var nodes = document.XPathSelectElements(

"//b:book[not(b:price[ > 10.00])]/b:price",namespaceMgr);

//All books whose price is not greater than 10.00

foreach (var node in nodes)

{

Response.Write(node.Value + "<BR/>");

}

Notice that the added method in Listing 10-12q,XPathSelectElements, still requires an

IXmlNames-paceResolver, so we create a newNameTableand map the namespaces and prefixes explicitly via

XmlNamespaceManager When using XElements and simple queries, you’re better off using LINQ to XML and the new XElement-specific methods such asElements()andDescendants()rather than XPath

Trang 4

TheSystem.Datanamespace andSystem.Xmlnamespace have started mingling their functionality for

some time DataSets are a good example of how relational data and XML data meet in a hybrid class

library During the COM and XML heyday, the ADO 2.5 recordset sported the capability to persist as

XML The dramatic inclusion of XML functionality in a class library focused entirely on manipulation

of relational data was a boon for developer productivity XML could be pulled out of SQL Server and

manipulated

Persisting DataSets to XML

Classes withinSystem.DatauseXmlWriterandXmlReaderin a number of places Now that you’re more

familiar withSystem.Xmlconcepts, be sure to take note of the method overloads provided by the classes

withinSystem.Data For example, theDataSet.WriteXmlmethod has four overloads, one of which

takes inXmlWriter Most of the methods withSystem.Dataare very pluggable with the classes from

System.Xml Listing 10-14 shows another way to retrieve the XML from relational data by loading a

DataSet from a SQL command and writing it directly to the browser with theResponseobject’s

OutputStreamproperty usingDataSet.WriteXml

Listing 10-14: Extracting XML from a SQL Server with System.Data.DataSet

VB

Dim connStr As String = "database=Northwind;Data Source=localhost; " _

& "User id=sa;pwd=wrox"

Using conn As New SqlConnection(connStr)

Dim command As New SqlCommand("select * from customers", conn)

conn.Open()

Dim ds As New DataSet()

ds.DataSetName = "Customers"

ds.Load(command.ExecuteReader(), LoadOption.OverwriteChanges, "Customer")

Response.ContentType = "text/xml"

ds.WriteXml(Response.OutputStream)

End Using

C#

string connStr = "database=Northwind;Data Source=localhost;User id=sa;pwd=wrox";

using (SqlConnection conn = new SqlConnection(connStr))

{

SqlCommand command = new SqlCommand("select * from customers", conn);

conn.Open();

DataSet ds = new DataSet();

ds.DataSetName = "Customers";

ds.Load(command.ExecuteReader(), LoadOption.OverwriteChanges, "Customer");

Response.ContentType = "text/xml";

ds.WriteXml(Response.OutputStream);

}

DataSets have a fairly fixed format, as illustrated in this example The root node of the document is

Customers, which corresponds to theDataSetNameproperty DataSets contain one or more named

DataTableobjects, and the names of theseDataTablesdefine the wrapper element — in this case,

Customer The name of theDataTableis passed into theloadmethod of the DataSet The correlation

Trang 5

between the DataSet’s name,DataTable’s name, and the resulting XML is not obvious when using

DataSets The resulting XML is shown in the browser in Figure 10-4

Figure 10-4

DataSets present a data model that is very different from the XML way of thinking about data Much

of the XML-style of thinking revolves around the InfoSet or the DOM, whereas DataSets are row- and

column-based TheXmlDataDocumentis an attempt to present these two ways of thinking into one

relatively unified model

XmlDataDocument

Although DataSets have their own relatively inflexible format for using XML, theXmlDocumentclass does not In order to bridge this gap, an unusual hybrid object, theXmlDataDocument, is introduced This object maintains the full fidelity of all the XML structure and allows you to access XML via theXmlDocument

API without losing the flexibility of a relational API AnXmlDataDocumentcontains a DataSet of its own and can be called DataSet-aware Its internal DataSet offers a relational view of the XML data Any data contained within the XML data document that does not map into the relational view is not lost, but

becomes available to the DataSet’s APIs

Trang 6

TheXmlDataDocumentis a constructor that takes a DataSet as a parameter Any changes made to the

XmlDataDocumentare reflected in the DataSet and vice versa

Now take the DataSet loaded in Listing 10-14 and manipulate the data with theXmlDataDocumentand

DOM APIs you’re familiar with Next, jump back into the world ofSystem.Dataand see that the DataSets

underlying DataRows have been updated with the new data, as shown in Listing 10-15

Listing 10-15: Changing DataSets using the DOM APIs from XmlDataDocument

VB

Dim connStr As String = "database=Northwind;Data Source=localhost; " _

& "User id=sa;pwd=wrox"

Using conn As New SqlConnection(connStr)

Dim command As New SqlCommand("select * from customers", conn)

conn.Open()

Dim ds As New DataSet()

ds.DataSetName = "Customers"

ds.Load(command.ExecuteReader(), LoadOption.OverwriteChanges, "Customer")

’Response.ContentType = "text/xml"

’ds.WriteXml(Response.OutputStream)

’Added in Listing 10-15

Dim doc As New XmlDataDocument(ds)

doc.DataSet.EnforceConstraints = False

Dim node As XmlNode = _

doc.SelectSingleNode("//Customer[CustomerID = ’ANATR’]/ContactTitle")

node.InnerText = "Boss"

doc.DataSet.EnforceConstraints = True

Dim dr As DataRow = doc.GetRowFromElement(CType(node.ParentNode, XmlElement))

Response.Write(dr("ContactName").ToString() & " is the ")

Response.Write(dr("ContactTitle").ToString())

End Using

C#

string connStr = "database=Northwind;Data Source=localhost; "

+ "User id=sa;pwd=wrox";

using (SqlConnection conn = new SqlConnection(connStr))

{

SqlCommand command = new SqlCommand("select * from customers", conn);

conn.Open();

DataSet ds = new DataSet();

ds.DataSetName = "Customers";

ds.Load(command.ExecuteReader(), LoadOption.OverwriteChanges,"Customer");

//Response.ContentType = "text/xml";

//ds.WriteXml(Response.OutputStream);

//Added in Listing 10-15

XmlDataDocument doc = new XmlDataDocument(ds);

doc.DataSet.EnforceConstraints = false;

XmlNode node = doc.SelectSingleNode(@"//Customer[CustomerID

= ’ANATR’]/ContactTitle");

Trang 7

node.InnerText = "Boss";

doc.DataSet.EnforceConstraints = true;

DataRow dr = doc.GetRowFromElement((XmlElement)node.ParentNode);

Response.Write(dr["ContactName"].ToString() + " is the ");

Response.Write(dr["ContactTitle"].ToString());

}

Listing 10-15 extends Listing 10-14 by first commenting out changing the HTTPContentTypeand the call

toDataSet.WriteXml After the DataSet is loaded from the database, it is passed to theXmlDataDocument

constructor At this point, theXmlDataDocumentand the DataSet refer to the same set of information

TheEnforceConstraintsproperty of the DataSet is set tofalseto allow changes to the DataSet When

EnforceConstraintsis later set totrue, if any constraint rules were broken, an exception is thrown

AnXPathexpression is passed to the DOM methodSelectSingleNode, selecting theContactTitle

node of a particular customer, and its text is changed toBoss Then by callingGetRowFromElementon

theXmlDataDocument, the context jumps from the world of theXmlDocumentback to the world of the

DataSet Column names are passed into theindexingproperty of the returnedDataRow, and the output

is shown in this line:

Ana Trujillo is the Boss

The data is loaded from the SQL server and then manipulated and edited withXmlDocument-style

methods; a string is then built using aDataRowfrom the underlying DataSet

XML is clearly more than just angle brackets XML data can come from files, from databases, from

information sets like the DataSet object, and certainly from the Web Today, however, a considerable

amount of data is stored in XML format, so a specific data source control has been added to ASP.NET 2.0 just for retrieving and working with XML data

The XmlDataSource Control

TheXmlDataSourcecontrol enables you to connect to your XML data and to use this data with any of

the ASP.NET data-bound controls Just like theSqlDataSourceand theAccessDataSourcecontrols, the

XmlDataSourcecontrol also enables you not only to retrieve data, but also to insert, delete, and update

data items

One unfortunate caveat of the XmlDataSource is that its XPath attribute does not

support documents that use namespace qualification Examples in this chapter use

the Books.xml file with a default namespace of http://examples.books.com It is

very common for XML files to use multiple namespaces, including a default

namespace As you learned when you created an XPathDocument and queried it with

XPath, the namespace in which an element exists is very important The regrettable

reality is, there is no way to use a namespace qualified XPath expression or to make

the XmlDataSource Control aware of a list of prefix/namespace pairs via the

XmlNamespaceManager class However, the XPath function used in the ItemTemplate

of the templated DataListcontrol can take aXmlNamespaceManager as its second

parameter and query XML returned from the XmlDataSource — as long as the

control does not include an XPath attribute with namespace qualification or you can

Trang 8

just omit it all together That said, in order for these examples to work, you must

remove the namespaces from your source XML and use XPath queries that include

no namespace qualification, as shown in Listing 10-16.

You can use aDataListcontrol or any DataBinding-aware control and connect to an<asp:

XmlDataSource>control The technique for binding a control directly to theBooks.xmlfile is illustrated

in Listing 10-16

Listing 10-16: Using a DataList control to display XML content

<%@ Page Language="VB" AutoEventWireup="false"

CodeFile="Default.aspx.vb" Inherits="Default_aspx" %>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head id="Head1" runat="server">

<title>XmlDataSource</title>

</head>

<body>

<form id="form1" runat="server">

<asp:datalist id="DataList1" DataSourceID="XmlDataSource1" runat="server">

<ItemTemplate>

<p><b><%# XPath("author/first-name") %>

<%# XPath("author/last-name")%></b>

wrote <%# XPath("title") %></p>

</ItemTemplate>

</asp:datalist>

<asp:xmldatasource id="XmlDataSource1" runat="server"

datafile="~/Books.xml"

xpath="//bookstore/book"/>

</form>

</body>

</html>

This is a simple example, but it shows you the ease of using theXmlDataSourcecontrol You should focus

on two attributes in this example The first is theDataFileattribute This attribute points to the location

of the XML file Because the file resides in the root directory of the application, it is simply∼/Books.xml

The next attribute included in theXmlDataSourcecontrol is theXPathattribute TheXmlDataSource

control uses theXPathattribute for the filtering of XML data In this case, theXmlDataSourcecontrol

is taking everything within the<book>set of elements The value//bookstore/bookmeans that the

XmlDataSourcecontrol navigates to the<bookstore>element and then to the<book>element within

the specified XML file and returns a list of all books

TheDataListcontrol then must specify itsDataSourceIDas theXmlDataSourcecontrol In the

<ItemTemplate>section of theDataListcontrol, you can retrieve specific values from the XML file by

using XPath commands within the template The XPath commands filter the data from the XML file

The first value retrieved is an element attribute (author/first-name) that is contained in the<book>

element If you are retrieving an attribute of an element, you preface the name of the attribute with an

at (@) symbol The next two XPath commands get the last name and the title of the book Remember

Trang 9

to separate nodes with a forward slash (/) When run in the browser, this code produces the results

illustrated in the following list:

Benjamin Franklin wrote The Autobiography of Benjamin Franklin

Herman Melville wrote The Confidence Man

Sidas Plato wrote The Gorgias

Note that if you wrote the actual code, this entire exercise would be done entirely in the ASPX page itself! Besides working from static XML files such as theBooks.xmlfile shown earlier, theXmlDataSource

control has the capability to work from dynamic, URL-accessible XML files One popular XML format

that is pervasive on the Internet today is the weblog These blogs, or personal diaries, can be viewed either

in the browser, through an RSS-aggregator, or as pure XML

In Figure 10-5, you can see the XML from my blog’s RSS feed I’ve saved the XML to a local file and

removed a stylesheet so I can see what the XML looks like when viewed directly in the browser (You

can find a lot of blogs to play with for this example atweblogs.asp.net.)

Figure 10-5

Trang 10

Now that you know the location of the XML from the blog, you can use this XML with theXmlDataSource

control and display some of the results in aDataListcontrol The code for this example is shown in

Listing 10-17

Listing 10-17: Displaying an XML RSS blog feed

<%@ Page Language="VB"%>

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">

<title>XmlDataSource</title>

</head>

<body>

<form id="form1" runat="server">

<asp:DataList ID="DataList1" Runat="server" DataSourceID="XmlDataSource1">

<HeaderTemplate>

<table border="1" cellpadding="3">

</HeaderTemplate>

<ItemTemplate>

<tr><td><b><%# XPath("title") %></b><br />

<i><%# XPath("pubDate") %></i><br />

<%# XPath("description") %></td></tr>

</ItemTemplate>

<AlternatingItemTemplate>

<tr bgcolor="LightGrey"><td><b><%# XPath("title") %></b><br />

<i><%# XPath("pubDate") %></i><br />

<%# XPath("description") %></td></tr>

</AlternatingItemTemplate>

<FooterTemplate>

</table>

</FooterTemplate>

</asp:DataList>

<asp:XmlDataSource ID="XmlDataSource1" Runat="server"

DataFile="http://www.hanselman.com/blog/feed"

XPath="rss/channel/item">

</asp:XmlDataSource>

</form>

</body>

</html>

Looking at the code in Listing 10-17, you can see that theDataFilepoints to a URL where the XML

is retrieved TheXPathproperty filters and returns all the<item>elements from the RSS feed The

DataListcontrol creates an HTML table and pulls out specific data elements from the RSS feed, such as

the<title>,<pubDate>, and<description>elements

Running this page in the browser, you get something similar to the results shown in Figure 10-6

This approach also works with XML Web services, even ones for which you can pass in parameters using

HTTP-GET You just set up theDataFileproperty value in the following manner:

DataFile="http://www.someserver.com/GetWeather.asmx/ZipWeather?zipcode=63301"

Ngày đăng: 05/07/2014, 18:20

TỪ KHÓA LIÊN QUAN