Directory listing of http: uap.unnes.ac.id ebook biblebook Visual Basic 6 com & Library Books
22
C H A P T E R
Integrating XM L
with Internet
Information
Server
Applications
I
n this c hapter, I’ll sho w yo u ho w to use the Do c ument
Objec t Mo del by building a Web page using VBSc ript. That
Web page will c o mmunic ate with a Web server applic atio n
built with Internet Info rmatio n Server (IIS) Applic atio ns.
Requesting Information
Ho w o ften have yo u wanted to impo rt a partic ular piec e o f
info rmatio n via the Web into yo ur pro gram fo r analysis?
Perhaps yo u’re interested in getting a sto c k quo te o n a perio dic rate o r fo llo wing mo rtgage rates? Maybe yo u want to
do wnlo ad info rmatio n abo ut ho w well the Orio les are playing.
By defining an XML do c ument fo r requesting info rmatio n and
ano ther do c ument to c o ntain the respo nse, yo u c an build a
new breed o f server that respo nds to XML requests fo r info rmatio n. The fac t that yo u c an leverage existing HTTP tec hno lo gies, suc h as Web servers and Web develo pment to o ls,
makes it easier to build these applic atio ns.
✦
✦
✦
In This Cha pter
✦
484
Part V ✦ The Impact of XM L
Getting Customer Information With XM L
In this c hapter, I’m go ing to fo c us o n ho w to build an XML c lient pro gram that
requests info rmatio n fro m an XML Server pro gram. I’ve dec ided to build a Web
page using a little VBSc ript as the c lient and an IIS Applic atio n as the server (see
Figure 22-1). This applic atio n suppo rts two basic types o f requests: retrieving info rmatio n abo ut a c usto mer and updating info rmatio n abo ut a c usto mer.
Figure 22-1: Running the XML Server application
Building the Simple Web Page
The sample Web page sho wn in Figure 22-1 is a fairly simple Web page that uses a
table to line up the c aptio ns and the fields I use to display the data, as yo u c an see
in Listing 22-1. It is bro ken into three main sec tio ns: the , the , and
the . While I’ve left the tags fo r in Listing 22-1, I o mitted the
c o de, sinc e I’ll disc uss it later in this sec tio n.
Listing 22-1: HTM L for the XM L client Web page
Address Information
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Address Information
Customer Id:
Name:
Street:
City/State/Zip:
Get Customer Info
Update Customer
Info
No te that the fo rm dec laratio n differs fro m mo st Web pages that use fo rms. In this
c ase, I do n’t need attributes that desc ribe ho w to send the fo rm data to the server.
Spec ific ally, I didn’t c o de the action and method attributes. This is bec ause I simply do n’t need them. The ro utines that will handle the c o nversio n to XML will also
handle the interac tio ns with the Web server.
485
486
Part V ✦ The Impact of XM L
At the bo tto m o f the fo rm, I dec lared butto ns that will c all the GetCustomerInfo
and UpdateCustomerInfo VBSc ript ro utines. This is where the ac tual wo rk o f c o nverting the info rmatio n fro m the fo rm into an XML do c ument and sending it to the
server fo r pro c essing takes plac e.
Requesting Customer Information
Retrieving c usto mer info rmatio n invo lves determining ho w the request and
respo nse XML do c uments sho uld lo o k and then building the c o de to pro c ess the
do c uments.
Defining the XM L documents
The GetCustomerInfo sc ript ro utine takes the CustomerId field fro m the fo rm o n
the Web page and assembles the XML do c ument sho wn in Listing 22-2. This do c ument defines the GETCUSTOMERINFO element to identify the request. Within the GETCUSTOMERINFO element are o ne o r mo re CUSTOMER elements with the CustomerId
attribute c o ded. This attribute spec ifies the c usto mer yo u want to retrieve.
Listing 22-2: A sample request for customer information
Listng 22-3 sho ws ho w the server sho uld respo nd to the request. I use the same
basic do c ument that was used to request the c usto mer’s info rmatio n, but I expand
the CUSTOMER element to inc lude elements fo r the Name, Street, City, State, and Zip
fields fro m the Custo mers table. I also inc lude ano ther attribute c alled Get, whic h
indic ates the status o f the request. A value o f OK means that the info rmatio n was
retrieved pro perly. Otherwise, Get will c o ntain an erro r message.
Listing 22-3: A sample response to the request for customer
information
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Dexter Valentine
3250 Second Ave.
San Francisco
CA
94115
Requesting a customer
Pressing the Get Custo mer Info butto n o n the Web page will trigger the
GetCustomerInfo VBSc ript ro utine in the sec tio n o f the HTML do c ument ( see Listing 22-4) . This ro utine perfo rms three separate tasks. First, it must
c reate an XML do c ument similar to the o ne sho wn in Listing 22-2. Next, it must
take the do c ument and transmit it to the Web server. Finally, it must take the
respo nse do c ument ( see Listing 22-3) fro m the Web server and fill in the vario us
fields o n the fo rm.
Listing 22-4: The GetCustomerInfo routine in XM L Client
Sub GetCustomerInfo()
Set XMLReq = CreateObject(“MSXML2.DOMDocument”)
Set p = XMLReq.createProcessingInstruction(“xml”, _
“version=””1.0”””)
XMLReq.appendChild p
Set node = XMLReq.createElement(“GETCUSTOMERINFO”)
Set subnode = XMLReq.createElement(“CUSTOMER”)
subnode.setAttribute “CustomerId”, _
Document.AddressInfo.CustomerId.Value
node.appendChild subnode
Continued
487
488
Part V ✦ The Impact of XM L
Listing 22-4 (continued)
XMLReq.appendChild node
MsgBox XMLReq.xml
set http=CreateObject(“MSXML2.XMLHTTP”)
http.open “Post”, _
“http://athena/VB6DB22/VB6DB22.ASP?wci=GetCustomer”,
false
http.setRequestHeader “Content-Type”, “text/xml”
http.send XMLReq
Set XMLResp = CreateObject(“MSXML2.DOMDocument”)
XMLResp.LoadXML http.responsetext
MsgBox XMLResp.xml
Set nl = XMLResp.getElementsByTagName(“CUSTOMER”)
i = 0
Do While (i < nl.length) And (nl(i).getAttribute(“CustomerId”)
_
Document.AddressInfo.CustomerId.Value)
i = i + 1
Loop
If i < nl.length Then
If nl(i).getAttribute(“Get”) = “OK” Then
Set nx = nl(i).getElementsByTagName(“NAME”)
Document.AddressInfo.Name.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“STREET”)
Document.AddressInfo.Street.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“CITY”)
Document.AddressInfo.City.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“STATE”)
Document.AddressInfo.State.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“ZIP”)
Document.AddressInfo.Zip.Value = nx(0).text
Else
MsgBox “The customer wasn’t found: “ & _
nl(i).getAttribute(“Get”)
Else
MsgBox “The customer wasn’t found.”
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
End If
End Sub
Note
The format’s changed to protect the guilty: I adm it it. I’ve reform atted all of the
HTML and script code from the actual docum ents to m ake them m ore readable.
How ever, changing the form atting does not change how the Web page w orks.
Building the request document
The GetCustomerInfo ro utine begins by c reating a DOMDocument o bjec t c alled
XMLReq to ho ld the XML do c ument I want to send to the server. No te that I c an’t use
the no rmal Dim and Set statements to c reate the o bjec t, bec ause VBSc ript c an’t referenc e the o bjec t libraries direc tly fro m c o de. The o nly way to c reate an o bjec t in
VBSc ript is to use the CreateObject func tio n.
After c reating the base do c ument, I add the element by
using the createProcessingInstruction and appendChild metho ds. While this
isn’t abso lutely nec essary, sinc e the MSXML parser is smart eno ugh to figure o ut
ho w yo ur do c ument is struc tured witho ut it, it is go o d fo rm to inc lude this element
in c ase yo u c ho o se to use a different XML server in the future.
Onc e the XML do c ument is initialized, I c reate the GETCUSTOMERINFO element that
really defines this do c ument by using the createElement metho d. This returns an
o bjec t referenc e to an XMLDOMElement o bjec t, whic h I save in the variable c alled
node. Then I c reate ano ther XMLDOMElement o bjec t fo r CUSTOMER in the variable
subnode. I use the setAttribute metho d to c reate the CustomerId attribute with
the value fro m the CustomerId field in the fo rm. Then I c o nnec t the subnode o bjec t
to the node o bjec t by using the node.appendChild metho d. Next, I use the
XMLReq.appendChild metho d to link the node o bjec t to the ro o t do c ument.
I sho uld po int o ut that the o rder in whic h I append the pro c essing and element
instruc tio ns to the ro o t o bjec t is impo rtant. All o f the o bjec ts sto red belo w a partic ular hierarc hy are sto red in the o rder where they were inserted. Thus, if yo u want
element A to be displayed befo re element B when the XML do c ument is generated,
yo u must append element A befo re yo u append element B. Sinc e I want the GETCUSTOMERINFO element to fo llo w the pro c essing instruc tio n element, I have to
append the pro c essing instruc tio n first.
After c reating the do c ument, I use the MsgBox statement (see Figure 22-2) and the
XMLReq.xml metho d to display the do c ument to the user. While this wo uldn’t be
inc luded in a pro duc tio n versio n o f this applic atio n, it allo ws the pro grammer to
see the XML request befo re it is sent.
489
490
Part V ✦ The Impact of XM L
Figure 22-2: View ing the XML
GETCUSTOMERINFO
request docum ent
Sending the request document
In the next sec tio n o f the ro utine, I c reate an XMLHttp o bjec t c alled http to perfo rm
the ac tual data transfer. After c reating http, I use the open metho d to establish an
HTTP c o nnec tio n to the Web server. I spec ify that I want to perfo rm an HTTP Po st
o peratio n to send the do c ument, and I inc lude the URL o f the pro gram that will pro c ess the request. Finally, I c ho o se no t to do an async hro no us transfer. This means
that the send metho d wo n’t return until a respo nse has been rec eived fro m the Web
server. This appro ac h simplifies the pro gramming invo lved, sinc e I do n’t have to
enable the onreadystatechange event to determine when the respo nse do c ument
has been rec eived.
Befo re I send the do c ument, I use the setRequestHeader metho d to set the
Co ntent-Type HTTP header explic itly to text/xml. While this isn’t impo rtant in
this applic atio n, sinc e bo th sides are expec ting XML do c uments to be transferred,
it may be impo rtant in o ther situatio ns where different pro c essing paths may be
taken depending o n the do c ument type.
When the c o de reac hes the send metho d, a warning message may be displayed to
the user letting them kno w that the Web page is ac c essing external info rmatio n (see
Figure 22-3). Yo u c an c o nfigure the Web bro wser to allo w pro grams to disable this
erro r message by c hanging the sec urity level to lo w fo r the partic ular zo ne that yo u
are ac c essing.
Figure 22-3: Getting perm ission to
end the XML docum ent
Caution
Do I really want to do this?: Changing the security level in your brow ser to allow
you to use the send m ethod in your Web page allow s any Web page in the sam e
content zone to use this function. Before you change this option, be sure you
really w ant to take this security risk.
After using the send metho d to transmit the do c ument, I c reate a new DOMDocument
o bjec t that will ho ld the respo nse fro m the Web server. Then I use the LoadXML
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
metho d to c reate the do c ument fro m the http.responsetext pro perty and then use
the MsgBox statement to display the respo nse do c ument to the user (see Figure 22-4).
Figure 22-4: View ing the GETCUSTOMERINFO response docum ent
Displaying the response document
Displaying the info rmatio n is merely a matter o f wo rking yo ur way thro ugh the
respo nse fro m the Web server and extrac ting the info rmatio n yo u want to display.
This is easier said than do ne, ho wever. Yo u need to traverse the do c ument hierarc hy to find the CUSTOMER element that matc hes the Custo merId value fro m the
fo rm. Then yo u need to determine if the request was suc c essful. Onc e this is do ne,
yo u c an take the info rmatio n asso c iated with the request and update the fo rm.
In this c ase, I begin by c reating a nodeList o bjec t that c o ntains all o f the CUSTOMER
elements using the getElementsByTagName metho d. Sinc e it is po ssible that the
nodeList o bjec t may have mo re than o ne CUSTOMER element, I’ll set the variable i
to zero and use a Do While lo o p to c hec k eac h o f the elements to find the first o ne
that matc hes the Custo merId value fro m the fo rm.
When the lo o p finishes, the variable i will either po int to the pro per element o r it
will c o ntain a value that is o ne larger than the number o f elements in the nodeList
o bjec t. (Remember that the nodeList o bjec t is a zero -based c o llec tio n, so if it c o ntains o nly o ne element, the element will have an index value o f zero while the c o llec tio n has a length o f o ne.)
Next, I c hec k the value o f i to see if it is less than the length o f the c o llec tio n and
issue the appro priate message if it isn’t. Then I c an see if the value o f the Get
attribute is OK. If it isn’t, I need to issue the appro priate erro r message.
If everything wo rked c o rrec tly, I c an retrieve the info rmatio n fo r eac h o f the fields
o n the fo rm by c reating a new nodeList o bjec t by searc hing fo r a partic ular element within the c urrent no de ( nl(i)). Sinc e the fo rmat o f the do c ument allo ws
o nly o ne element with a partic ular name within the CUSTOMER element, I c an safely
ac c ess the first value in the returned nodeList sinc e I kno w it must be the o nly element in the list. Then I c an use the text pro perty to extrac t the value o f the
XMLDOMText no de belo w it and save it in the appro priate field o n the fo rm. This
results in the updated Web page sho wn in Figure 22-5.
491
492
Part V ✦ The Impact of XM L
Figure 22-5: View ing the custom er’s inform ation
Getting a customer from the database
No w that yo u understand the c lient side, it’s time to dig into the server side. Sinc e
this is an IIS Applic atio n, it respo nds to requests sent to an Internet Info rmatio n
Server (IIS) Web server. In this c ase, it must respo nd to an XML do c ument that is
transmitted using the Post metho d. It must parse the inc o ming XML do c ument to
determine the info rmatio n that is requested and then c o nstruc t a new XML do c ument with the appro priate respo nse.
The GetCustomer_Respond event in the XML Server pro gram is triggered any time
so meo ne requests a do c ument using the fo llo wing URL:
http://Athena/VB6DB22/VB6DB22.ASP?wci=GetCustomer
This URL po ints to a c o mputer c alled Athena and lo o ks in the VB6DB22 direc to ry
fo r the file c alled VB6DB22.ASP. It passes the wci=GetCustomer parameter to the
file, whic h will trigger the GetCustomer_Respond event in the IIS Applic atio n (see
Listing 22-5).
Listing 22-5: The GetCustomer_Respond event in XM L Server
Private Sub GetCustomer_Respond()
Dim attr As IXMLDOMAttribute
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
el As IXMLDOMElement
nl As IXMLDOMNodeList
node As IXMLDOMElement
p As IXMLDOMProcessingInstruction
subnode As IXMLDOMElement
subsubnode As IXMLDOMElement
XMLReq As DOMDocument
XMLResp As DOMDocument
z() As Byte
Dim db As ADODB.Connection
Dim rs As ADODB.Recordset
z = Request.BinaryRead(10000)
Set XMLReq = New DOMDocument
XMLReq.loadXML StrConv(z, vbUnicode)
Set nl = XMLReq.getElementsByTagName(“CUSTOMER”)
Set XMLResp = New DOMDocument
Set p = XMLResp.createProcessingInstruction(“xml”, _
“version=””1.0”””)
XMLResp.appendChild p
Set node = XMLResp.createElement(“GETCUSTOMERINFO”)
XMLResp.appendChild node
Set db = New ADODB.Connection
db.Open _
“provider=sqloledb;data source=Athena;initial catalog=VB6DB”,
_
“sa”, “”
Set rs = New ADODB.Recordset
Set rs.ActiveConnection = db
For Each el In nl
rs.Source = “Select * From Customers Where CustomerId = “ & _
el.getAttribute(“CustomerId”)
rs.Open
If Not ((rs.BOF) And (rs.EOF)) Then
Set subnode = XMLResp.createElement(“CUSTOMER”)
Set attr = XMLResp.createAttribute(“CustomerId”)
attr.Text = rs(“CustomerId”).Value
subnode.Attributes.setNamedItem attr
Set attr = XMLResp.createAttribute(“Get”)
attr.Text = “OK”
subnode.Attributes.setNamedItem attr
Continued
493
494
Part V ✦ The Impact of XM L
Listing 22-5 (continued)
node.appendChild subnode
Set subsubnode = XMLResp.createElement(“NAME”)
subsubnode.Text = rs(“Name”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“STREET”)
subsubnode.Text = rs(“Street”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“CITY”)
subsubnode.Text = rs(“City”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“STATE”)
subsubnode.Text = rs(“State”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“ZIP”)
subsubnode.Text = rs(“Zip”).Value
subnode.appendChild subsubnode
Else
Set subnode = XMLResp.createElement(“CUSTOMER”)
Set attr = XMLResp.createAttribute(“CustomerId”)
attr.Text = el.getAttribute(“CustomerId”)
subnode.Attributes.setNamedItem attr
Set attr = XMLResp.createAttribute(“Get”)
attr.Text = “Not found”
subnode.Attributes.setNamedItem attr
node.appendChild subnode
End If
rs.Close
Next el
XMLResp.Save Response
db.Close
Set XMLResp = Nothing
Set XMLReq = Nothing
Set rs = Nothing
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Set db = Nothing
End Sub
Preparing to respond to the request
After dec laring a who le lo t o f lo c al variables, I begin pro c essing by using the
Request.BinaryRead to get the input do c ument into a byte array. Next, I c reate
a new instanc e o f the DOMDocument o bjec t that will ho ld the request, and use the
loadXML metho d to build the do c ument o bjec t hierarc hy. No te that I used the
StrConv func tio n to c o nvert the ASCII enc o ded string into Unic o de befo re lo ading
it with the loadXML metho d. Finally, I use the getElementsByTagName metho d to
c reate a list o f all o f the CUSTOMER elements.
Then I c reate a new instanc e o f the respo nse do c ument ( XMLResp) and initialize it
with the standard XML versio n info rmatio n. Next, I will append a GETCUSTOMERINFO
o bjec t that will c o ntain the individual CUSTOMER elements that fo rm the respo nse.
In o rder to ac c ess the database, I c reate a new instanc e o f the ADODB.Connection
o bjec t and use the Open metho d to lo g o nto the database server. Then I c reate a
new instanc e o f the ADODB.Recordset o bjec t and set the ActiveConnection pro perty to the Connection o bjec t I just o pened.
Building the response
After all o f the prep wo rk, I use a For Each lo o p to ac c ess eac h CUSTOMER element
in the nodeList c o llec tio n. Using the info rmatio n fro m the CustomerId attribute, I
build a Select statement to retrieve info rmatio n abo ut the spec ified Custo merId
value and then o pen the Recordset o bjec t.
If the Recordset o bjec t c o ntains at least o ne rec o rd ( Not (rs.BOF And rs.EOF)
is True), I’ll c reate a new CUSTOMER element no de using the createElement
metho d, and set the CustomerId to the c urrent value o f Custo merId and the Get
attribute to OK.
Fo r eac h o f the fields that I want to return, I c reate a new element no de and assign
it the value fro m the c o rrespo nding database field. Then I add it to the CUSTOMER
element I c reated earlier. After I add all o f the elements, I c lo se the Recordset
o bjec t.
If the Select didn’t return any ro ws, I’ll c reate a CUSTOMER element with the
CustomerId and Get attributes as befo re, but rather than assigning the Get attribute a value o f OK, I’ll return “Not found”. Afterwards, I’ll c lo se the Recordset
o bjec t fo r the partic ular CUSTOMER element and repeat the For Each lo o p until
I’m o ut o f CUSTOMER elements to pro c ess.
495
496
Part V ✦ The Impact of XM L
Finally, I’ll use the XMLResp.Save metho d against the Response o bjec t. This will
auto matic ally take the XML do c ument sto red in the do c ument o bjec t mo del and
o utput the XML tags to the HTTP return stream. Onc e the do c ument is returned, I
c an c lo se the database c o nnec tio n and destro y the vario us o bjec ts I c reated while
pro c essing this request.
Updating Customer Information
Yo u’ve seen o ne way to handle a transac tio n using XML do c uments to c arry the
request and the respo nse. This is the basic way mo st XML data exc hanges will
o c c ur. It do esn’t matter if the do c ument exc hange returns info rmatio n o r perfo rms
a func tio n. As lo ng as the pro per info rmatio n is c o ntained in the do c ument, it really
do esn’t matter.
Ho wever, the GetCustomerInfo and GetCustomer_Respond ro utines are based o n
do c uments that are element-o riented. Eac h individual field is sto red in a separate
element. In the update pro c ess, I c ho o se to sto re eac h field as an element o f the
CUSTOMER element.
Defining the update XM L documents
When requesting an update, yo u need to inc lude all o f the fields that need to be
updated in the requesting do c ument. By using attributes instead o f elements, yo u
c an get a slightly smaller do c ument whic h pro bably wo n’t make muc h o f a differenc e in the lo ng run, but it do es result in a flatter hierarc hy whic h c an be easier to
pro c ess with yo ur applic atio n pro gram.
Listing 22-6 c o ntains a sample XML do c ument that wo uld be transmitted fro m the
XML c lient to the XML server to update a partic ular value. Eac h o f the fields to be
updated are sto red in a separate attribute, and the CustomerId attribute is used to
identify the c usto mer’s info rmatio n in the database.
Listing 22-6: An XM L document containing update
information
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
The do c ument to return the status o f the update is based o n the same do c ument
that was used to request the update (see Listing 22-7). The main differenc es are
that the individual attributes c o ntaining the data to be updated are no t returned,
while a new attribute c alled Update is added that will repo rt the status o f the
update.
Listing 22-7: An XM L document containing the results of the
update
Requesting an update
Clic king o n the Update Custo mer Info butto n will trigger the UpdateCustomerInfo
ro utine sho wn in Listing 22-8. This ro utine begins by c reating an o bjec t c alled
XMLReq, whic h will ho ld the XML request do c ument and insert the XML versio n pro c essing instruc tio n.
Listing 22-8: The UpdateCustomerInfo routine in XM L Client
Sub UpdateCustomerInfo()
Set XMLReq = CreateObject(“MSXML2.DOMDocument”)
Set p = XMLReq.createProcessingInstruction(“xml”,
“version=””1.0”””)
XMLReq.appendChild p
Set node = XMLReq.createElement(“UPDATECUSTOMERINFO”)
Set subnode = XMLReq.createElement(“CUSTOMER”)
subnode.setAttribute “CustomerId”, _
Document.AddressInfo.CustomerId.Value
subnode.setAttribute “Name”, Document.AddressInfo.Name.Value
subnode.setAttribute “Street”,
Document.AddressInfo.Street.Value
subnode.setAttribute “City”, Document.AddressInfo.City.Value
subnode.setAttribute “State”, Document.AddressInfo.State.Value
Continued
497
498
Part V ✦ The Impact of XM L
Listing 22-8 (continued)
subnode.setAttribute “Zip”, Document.AddressInfo.Zip.Value
node.appendChild subnode
XMLReq.appendChild node
MsgBox XMLReq.xml
set http=CreateObject(“MSXML2.XMLHTTP”)
http.Open “Post”, _
“http://athena/VB6DB22/VB6DB22.ASP?wci=UpdateCustomer”,
false
http.setRequestHeader “Content-Type”, “text/xml”
http.send XMLReq
Set XMLResp = CreateObject(“MSXML2.DOMDocument”)
XMLResp.LoadXML http.responsetext
MsgBox XMLResp.xml
End Sub
Next, I c reate the UPDATECUSTOMERINFO and CUSTOMER elements, whic h will ho ld
the request. Then I c an use the setAttribute metho d to add the vario us attribute
values to the CUSTOMER element. No te that the setAttribute metho d will auto matic ally c reate the XMLDOMAttribute o bjec t fo r the attribute if it do esn’t exist and
auto matic ally append it to the element. If the attribute o bjec t already exists, then
this metho d will merely update the value.
Befo re I send the do c ument to the server, I display it using a MsgBo x statement (see
Figure 22-6). Then I use the same tec hnique I used earlier to send the request to the
XML server and wait fo r its respo nse. When I rec eive the respo nse, I display the
respo nse to the user to let them kno w if the update was suc c essful o r no t (see
Figure 22-7).
Figure 22-6: Displaying the update request
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Figure 22-7: Displaying a successful update
Processing an update
On the server side, the UpdateCustomer_Respond event will b e triggered when
an XML do c ument arrives ( see Listing 22-9) . It uses the same pro c ess that the
GetCustomer_Respond metho d used to rec eive the XML do c ument, initialize the
return XML do c ument, and o pen a datab ase c o nnec tio n. I also selec t all o f the elements named CUSTOMER and save them in a nodeList o b jec t. Ho wever, fro m this
po int o n, the two ro utines differ signific antly.
Listing 22-9: The UpdateCustomer_Respond in XM L Server
Private Sub UpdateCustomer_Respond()
On Error Resume Next
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
attr As IXMLDOMAttribute
el As IXMLDOMElement
nl As IXMLDOMNodeList
node As IXMLDOMElement
p As IXMLDOMProcessingInstruction
parm As ADODB.Parameter
subnode As IXMLDOMElement
subsubnode As IXMLDOMElement
XMLReq As DOMDocument
XMLResp As DOMDocument
z() As Byte
Dim db As ADODB.Connection
Dim cmd As ADODB.Command
z = Request.BinaryRead(10000)
Set XMLReq = New DOMDocument
XMLReq.loadXML StrConv(z, vbUnicode)
Set nl = XMLReq.getElementsByTagName(“CUSTOMER”)
Set XMLResp = New DOMDocument
Continued
499
500
Part V ✦ The Impact of XM L
Listing 22-9 (continued)
Set p = XMLResp.createProcessingInstruction(“xml”, _
“version=””1.0”””)
XMLResp.appendChild p
Set node = XMLResp.createElement(“UPDATECUSTOMERINFO”)
XMLResp.appendChild node
Set db = New ADODB.Connection
db.Open _
“provider=sqloledb;data source=Athena;initial catalog=VB6DB”, _
“sa”, “”
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = db
cmd.CommandText = “Update Customers Set Name=?, Street=?, “ & _
“City=?, State=?, Zip=? Where CustomerId=?”
Set parm = cmd.CreateParameter(“Name”, adVarChar, adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Street”, adVarChar, _
adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“City”, adVarChar, adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“State”, adChar, adParamInput, 2)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Zip”, adInteger, adParamInput, 4)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“CustomerId”, adInteger, _
adParamInput, 4)
cmd.Parameters.Append parm
For Each el In nl
cmd.Parameters(“CustomerId”).Value = _
el.getAttribute(“CustomerId”)
cmd.Parameters(“Name”).Value = el.getAttribute(“Name”)
cmd.Parameters(“Street”).Value = el.getAttribute(“Street”)
cmd.Parameters(“City”).Value = el.getAttribute(“City”)
cmd.Parameters(“State”).Value = el.getAttribute(“State”)
cmd.Parameters(“Zip”).Value = el.getAttribute(“Zip”)
db.Errors.Clear
cmd.Execute
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Set subnode = XMLResp.createElement(“CUSTOMER”)
subnode.setAttribute “CustomerId”, _
cmd.Parameters(“CustomerId”).Value
If db.Errors.Count = 0 Then
subnode.setAttribute “Update”, “OK”
Else
subnode.setAttribute “Update”, db.Errors.Item(0).Description
End If
node.appendChild subnode
Next el
XMLResp.Save Response
Set XMLResp = Nothing
Set XMLReq = Nothing
db.Close
Set cmd = Nothing
Set db = Nothing
End Sub
I c ho se to c reate a parameterized Command o bjec t, whic h uses the Update statement to c hange the c o ntents o f the database. So , after c reating a new instanc e o f
the Command o bjec t, I c reate an Update statement listing eac h o f the fields I want to
update and assigning them a value o f questio n mark ( ?). The questio n mark is really
a plac eho lder that will be replac ed with the parameters asso c iated with the
Command o bjec t.
Then I c reate the Parameter o bjec ts fo r the Command o bjec t using the Create
Parameter metho d. I spec ify the name, data type, direc tio n, and length fo r eac h
parameter as I c reate it, then I Append it to the Command’s Parameters c o llec tio n.
No te that I c reate the Parameter o bjec ts in the same o rder that the questio n marks
appear. This is very impo rtant, sinc e the o nly way to asso c iate a parameter with the
statement is the o rder o f the parameters.
Onc e I’ve do ne all o f this setup wo rk, I’m ready to use a For Each lo o p to pro c ess
the list o f CUSTOMER elements. I use the getAttribute metho d to return the value
o f eac h o f the attributes fro m the XML request do c ument and save it as the value in
the c o rrespo nding Parameter o bjec t.
501
502
Part V ✦ The Impact of XM L
After defining the parameters, I clear the Connection object’s Errors collection and
Execute the command. Then I create the CUSTOMER element in the return document
and set the CustomerId property. If there were no database errors ( db.Errors.
Count = 0), I’ll set the Get attribute to OK; otherwise, I’ll set the Get attribute to
the Description property from the first element in the Errors collection.
No w I Append the CUSTOMER element to the XMLResp do c ument and retrieve the
next no de in the nodeList o bjec t. This pro c ess will c o ntinue until all o f the elements in the nodeList o bjec t have been pro c essed. I end the ro utine by saving
the XMLResp o bjec t to the Response stream, c lo sing the database c o nnec tio n
and destro ying the o bjec ts I used in this ro utine.
Thoughts about Programming XM L Documents
Without XML at your disposal, getting inform ation across the Web program m atically can be
difficult. You have to build com plicated program s that w ill dow nload a Web page containing the inform ation you w ant, and then try to parse it looking for the proper value. In addition, you have to update your program each tim e som eone updates the form at of the Web
page. How ever, XML offers an easier solution.
Using XML it is reasonable to build a pair of applications that com m unicate w ith each other
via the Internet using XML docum ents. The client program m ay be a traditional Visual Basic
program , or perhaps a JavaScript-based Web page, that generates an XML docum ent containing a request for inform ation. This request is then passed to a Web server, w hich
receives the XML docum ent, decodes it, and returns the data to the client program . Finally,
the client program extracts the inform ation it w ants from the return XML docum ent.
The nice thing about this approach is that you can use any tools you w ant on the client and
the server side. The only issue is that both program s m ust agree on the elem ents in the
XML docum ents that are exchanged. But as long as XML is used in the m iddle, the details of
the program s on each side aren’t im portant.
The program s can be coded in Visual Basic, VBScript, Java, C+ + , or even COBOL for that
m atter. They can run on Window s 2000 Server, Solaris, Linux, or OS/ 390. The point is, as
long as the XML is properly constructed, you have a vendor-independent solution.
You should consider the application I built here m erely as a toy to explore w hat you can do
w ith a little XML, HTML, and a Visual Basic program . I’m not saying that you should run out
and convert all of your applications to XML anytim e you need to pass inform ation. How ever,
XML is the w ave of the future, and anything you can do now to learn m ore about how to
use it w ill m ake your life easier in the future.
One of the problem s w ith m essage queues is that you need a w ay to pass inform ation
betw een the client application and the transaction server. While you can pass persisted
objects back and forth, they can be a pain to develop and debug. Since XML is hum an readable, it is easier to debug (trust m e —debugging a COM+ based m essage queue application
can be a real nightm are) w ithout losing any of the flexibility of objects it w ould replace.
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
You could easily com bine tools such as an IIS Application, COM+ transactions, m essage
queues, and XML to build a com plex, high-perform ance application that accepts vendorneutral requests coded in XML. This allow s you to develop clients for different platform s,
including such operating system s as Linux, Solaris, Macintosh, and even the occasional
OS/ 390 IBM m ainfram e.
Summary
In this c hapter yo u learned:
✦ ho w to design XML do c uments to request and rec eive info rmatio n fro m a
Web server.
✦ ho w to build an IIS Applic atio n that sends an XML request to a Web server.
✦ ho w to build an IIS Applic atio n to parse an XML do c ument.
✦ ho w to update a database using an XML do c ument.
✦
✦
✦
503
C H A P T E R
Integrating XM L
with Internet
Information
Server
Applications
I
n this c hapter, I’ll sho w yo u ho w to use the Do c ument
Objec t Mo del by building a Web page using VBSc ript. That
Web page will c o mmunic ate with a Web server applic atio n
built with Internet Info rmatio n Server (IIS) Applic atio ns.
Requesting Information
Ho w o ften have yo u wanted to impo rt a partic ular piec e o f
info rmatio n via the Web into yo ur pro gram fo r analysis?
Perhaps yo u’re interested in getting a sto c k quo te o n a perio dic rate o r fo llo wing mo rtgage rates? Maybe yo u want to
do wnlo ad info rmatio n abo ut ho w well the Orio les are playing.
By defining an XML do c ument fo r requesting info rmatio n and
ano ther do c ument to c o ntain the respo nse, yo u c an build a
new breed o f server that respo nds to XML requests fo r info rmatio n. The fac t that yo u c an leverage existing HTTP tec hno lo gies, suc h as Web servers and Web develo pment to o ls,
makes it easier to build these applic atio ns.
✦
✦
✦
In This Cha pter
✦
484
Part V ✦ The Impact of XM L
Getting Customer Information With XM L
In this c hapter, I’m go ing to fo c us o n ho w to build an XML c lient pro gram that
requests info rmatio n fro m an XML Server pro gram. I’ve dec ided to build a Web
page using a little VBSc ript as the c lient and an IIS Applic atio n as the server (see
Figure 22-1). This applic atio n suppo rts two basic types o f requests: retrieving info rmatio n abo ut a c usto mer and updating info rmatio n abo ut a c usto mer.
Figure 22-1: Running the XML Server application
Building the Simple Web Page
The sample Web page sho wn in Figure 22-1 is a fairly simple Web page that uses a
table to line up the c aptio ns and the fields I use to display the data, as yo u c an see
in Listing 22-1. It is bro ken into three main sec tio ns: the , the , and
the . While I’ve left the tags fo r in Listing 22-1, I o mitted the
c o de, sinc e I’ll disc uss it later in this sec tio n.
Listing 22-1: HTM L for the XM L client Web page
Address Information
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Address Information
Customer Id:
Name:
Street:
City/State/Zip:
Get Customer Info
Update Customer
Info
No te that the fo rm dec laratio n differs fro m mo st Web pages that use fo rms. In this
c ase, I do n’t need attributes that desc ribe ho w to send the fo rm data to the server.
Spec ific ally, I didn’t c o de the action and method attributes. This is bec ause I simply do n’t need them. The ro utines that will handle the c o nversio n to XML will also
handle the interac tio ns with the Web server.
485
486
Part V ✦ The Impact of XM L
At the bo tto m o f the fo rm, I dec lared butto ns that will c all the GetCustomerInfo
and UpdateCustomerInfo VBSc ript ro utines. This is where the ac tual wo rk o f c o nverting the info rmatio n fro m the fo rm into an XML do c ument and sending it to the
server fo r pro c essing takes plac e.
Requesting Customer Information
Retrieving c usto mer info rmatio n invo lves determining ho w the request and
respo nse XML do c uments sho uld lo o k and then building the c o de to pro c ess the
do c uments.
Defining the XM L documents
The GetCustomerInfo sc ript ro utine takes the CustomerId field fro m the fo rm o n
the Web page and assembles the XML do c ument sho wn in Listing 22-2. This do c ument defines the GETCUSTOMERINFO element to identify the request. Within the GETCUSTOMERINFO element are o ne o r mo re CUSTOMER elements with the CustomerId
attribute c o ded. This attribute spec ifies the c usto mer yo u want to retrieve.
Listing 22-2: A sample request for customer information
Listng 22-3 sho ws ho w the server sho uld respo nd to the request. I use the same
basic do c ument that was used to request the c usto mer’s info rmatio n, but I expand
the CUSTOMER element to inc lude elements fo r the Name, Street, City, State, and Zip
fields fro m the Custo mers table. I also inc lude ano ther attribute c alled Get, whic h
indic ates the status o f the request. A value o f OK means that the info rmatio n was
retrieved pro perly. Otherwise, Get will c o ntain an erro r message.
Listing 22-3: A sample response to the request for customer
information
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Dexter Valentine
3250 Second Ave.
San Francisco
CA
94115
Requesting a customer
Pressing the Get Custo mer Info butto n o n the Web page will trigger the
GetCustomerInfo VBSc ript ro utine in the sec tio n o f the HTML do c ument ( see Listing 22-4) . This ro utine perfo rms three separate tasks. First, it must
c reate an XML do c ument similar to the o ne sho wn in Listing 22-2. Next, it must
take the do c ument and transmit it to the Web server. Finally, it must take the
respo nse do c ument ( see Listing 22-3) fro m the Web server and fill in the vario us
fields o n the fo rm.
Listing 22-4: The GetCustomerInfo routine in XM L Client
Sub GetCustomerInfo()
Set XMLReq = CreateObject(“MSXML2.DOMDocument”)
Set p = XMLReq.createProcessingInstruction(“xml”, _
“version=””1.0”””)
XMLReq.appendChild p
Set node = XMLReq.createElement(“GETCUSTOMERINFO”)
Set subnode = XMLReq.createElement(“CUSTOMER”)
subnode.setAttribute “CustomerId”, _
Document.AddressInfo.CustomerId.Value
node.appendChild subnode
Continued
487
488
Part V ✦ The Impact of XM L
Listing 22-4 (continued)
XMLReq.appendChild node
MsgBox XMLReq.xml
set http=CreateObject(“MSXML2.XMLHTTP”)
http.open “Post”, _
“http://athena/VB6DB22/VB6DB22.ASP?wci=GetCustomer”,
false
http.setRequestHeader “Content-Type”, “text/xml”
http.send XMLReq
Set XMLResp = CreateObject(“MSXML2.DOMDocument”)
XMLResp.LoadXML http.responsetext
MsgBox XMLResp.xml
Set nl = XMLResp.getElementsByTagName(“CUSTOMER”)
i = 0
Do While (i < nl.length) And (nl(i).getAttribute(“CustomerId”)
_
Document.AddressInfo.CustomerId.Value)
i = i + 1
Loop
If i < nl.length Then
If nl(i).getAttribute(“Get”) = “OK” Then
Set nx = nl(i).getElementsByTagName(“NAME”)
Document.AddressInfo.Name.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“STREET”)
Document.AddressInfo.Street.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“CITY”)
Document.AddressInfo.City.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“STATE”)
Document.AddressInfo.State.Value = nx(0).text
Set nx = nl(i).getElementsByTagName(“ZIP”)
Document.AddressInfo.Zip.Value = nx(0).text
Else
MsgBox “The customer wasn’t found: “ & _
nl(i).getAttribute(“Get”)
Else
MsgBox “The customer wasn’t found.”
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
End If
End Sub
Note
The format’s changed to protect the guilty: I adm it it. I’ve reform atted all of the
HTML and script code from the actual docum ents to m ake them m ore readable.
How ever, changing the form atting does not change how the Web page w orks.
Building the request document
The GetCustomerInfo ro utine begins by c reating a DOMDocument o bjec t c alled
XMLReq to ho ld the XML do c ument I want to send to the server. No te that I c an’t use
the no rmal Dim and Set statements to c reate the o bjec t, bec ause VBSc ript c an’t referenc e the o bjec t libraries direc tly fro m c o de. The o nly way to c reate an o bjec t in
VBSc ript is to use the CreateObject func tio n.
After c reating the base do c ument, I add the element by
using the createProcessingInstruction and appendChild metho ds. While this
isn’t abso lutely nec essary, sinc e the MSXML parser is smart eno ugh to figure o ut
ho w yo ur do c ument is struc tured witho ut it, it is go o d fo rm to inc lude this element
in c ase yo u c ho o se to use a different XML server in the future.
Onc e the XML do c ument is initialized, I c reate the GETCUSTOMERINFO element that
really defines this do c ument by using the createElement metho d. This returns an
o bjec t referenc e to an XMLDOMElement o bjec t, whic h I save in the variable c alled
node. Then I c reate ano ther XMLDOMElement o bjec t fo r CUSTOMER in the variable
subnode. I use the setAttribute metho d to c reate the CustomerId attribute with
the value fro m the CustomerId field in the fo rm. Then I c o nnec t the subnode o bjec t
to the node o bjec t by using the node.appendChild metho d. Next, I use the
XMLReq.appendChild metho d to link the node o bjec t to the ro o t do c ument.
I sho uld po int o ut that the o rder in whic h I append the pro c essing and element
instruc tio ns to the ro o t o bjec t is impo rtant. All o f the o bjec ts sto red belo w a partic ular hierarc hy are sto red in the o rder where they were inserted. Thus, if yo u want
element A to be displayed befo re element B when the XML do c ument is generated,
yo u must append element A befo re yo u append element B. Sinc e I want the GETCUSTOMERINFO element to fo llo w the pro c essing instruc tio n element, I have to
append the pro c essing instruc tio n first.
After c reating the do c ument, I use the MsgBox statement (see Figure 22-2) and the
XMLReq.xml metho d to display the do c ument to the user. While this wo uldn’t be
inc luded in a pro duc tio n versio n o f this applic atio n, it allo ws the pro grammer to
see the XML request befo re it is sent.
489
490
Part V ✦ The Impact of XM L
Figure 22-2: View ing the XML
GETCUSTOMERINFO
request docum ent
Sending the request document
In the next sec tio n o f the ro utine, I c reate an XMLHttp o bjec t c alled http to perfo rm
the ac tual data transfer. After c reating http, I use the open metho d to establish an
HTTP c o nnec tio n to the Web server. I spec ify that I want to perfo rm an HTTP Po st
o peratio n to send the do c ument, and I inc lude the URL o f the pro gram that will pro c ess the request. Finally, I c ho o se no t to do an async hro no us transfer. This means
that the send metho d wo n’t return until a respo nse has been rec eived fro m the Web
server. This appro ac h simplifies the pro gramming invo lved, sinc e I do n’t have to
enable the onreadystatechange event to determine when the respo nse do c ument
has been rec eived.
Befo re I send the do c ument, I use the setRequestHeader metho d to set the
Co ntent-Type HTTP header explic itly to text/xml. While this isn’t impo rtant in
this applic atio n, sinc e bo th sides are expec ting XML do c uments to be transferred,
it may be impo rtant in o ther situatio ns where different pro c essing paths may be
taken depending o n the do c ument type.
When the c o de reac hes the send metho d, a warning message may be displayed to
the user letting them kno w that the Web page is ac c essing external info rmatio n (see
Figure 22-3). Yo u c an c o nfigure the Web bro wser to allo w pro grams to disable this
erro r message by c hanging the sec urity level to lo w fo r the partic ular zo ne that yo u
are ac c essing.
Figure 22-3: Getting perm ission to
end the XML docum ent
Caution
Do I really want to do this?: Changing the security level in your brow ser to allow
you to use the send m ethod in your Web page allow s any Web page in the sam e
content zone to use this function. Before you change this option, be sure you
really w ant to take this security risk.
After using the send metho d to transmit the do c ument, I c reate a new DOMDocument
o bjec t that will ho ld the respo nse fro m the Web server. Then I use the LoadXML
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
metho d to c reate the do c ument fro m the http.responsetext pro perty and then use
the MsgBox statement to display the respo nse do c ument to the user (see Figure 22-4).
Figure 22-4: View ing the GETCUSTOMERINFO response docum ent
Displaying the response document
Displaying the info rmatio n is merely a matter o f wo rking yo ur way thro ugh the
respo nse fro m the Web server and extrac ting the info rmatio n yo u want to display.
This is easier said than do ne, ho wever. Yo u need to traverse the do c ument hierarc hy to find the CUSTOMER element that matc hes the Custo merId value fro m the
fo rm. Then yo u need to determine if the request was suc c essful. Onc e this is do ne,
yo u c an take the info rmatio n asso c iated with the request and update the fo rm.
In this c ase, I begin by c reating a nodeList o bjec t that c o ntains all o f the CUSTOMER
elements using the getElementsByTagName metho d. Sinc e it is po ssible that the
nodeList o bjec t may have mo re than o ne CUSTOMER element, I’ll set the variable i
to zero and use a Do While lo o p to c hec k eac h o f the elements to find the first o ne
that matc hes the Custo merId value fro m the fo rm.
When the lo o p finishes, the variable i will either po int to the pro per element o r it
will c o ntain a value that is o ne larger than the number o f elements in the nodeList
o bjec t. (Remember that the nodeList o bjec t is a zero -based c o llec tio n, so if it c o ntains o nly o ne element, the element will have an index value o f zero while the c o llec tio n has a length o f o ne.)
Next, I c hec k the value o f i to see if it is less than the length o f the c o llec tio n and
issue the appro priate message if it isn’t. Then I c an see if the value o f the Get
attribute is OK. If it isn’t, I need to issue the appro priate erro r message.
If everything wo rked c o rrec tly, I c an retrieve the info rmatio n fo r eac h o f the fields
o n the fo rm by c reating a new nodeList o bjec t by searc hing fo r a partic ular element within the c urrent no de ( nl(i)). Sinc e the fo rmat o f the do c ument allo ws
o nly o ne element with a partic ular name within the CUSTOMER element, I c an safely
ac c ess the first value in the returned nodeList sinc e I kno w it must be the o nly element in the list. Then I c an use the text pro perty to extrac t the value o f the
XMLDOMText no de belo w it and save it in the appro priate field o n the fo rm. This
results in the updated Web page sho wn in Figure 22-5.
491
492
Part V ✦ The Impact of XM L
Figure 22-5: View ing the custom er’s inform ation
Getting a customer from the database
No w that yo u understand the c lient side, it’s time to dig into the server side. Sinc e
this is an IIS Applic atio n, it respo nds to requests sent to an Internet Info rmatio n
Server (IIS) Web server. In this c ase, it must respo nd to an XML do c ument that is
transmitted using the Post metho d. It must parse the inc o ming XML do c ument to
determine the info rmatio n that is requested and then c o nstruc t a new XML do c ument with the appro priate respo nse.
The GetCustomer_Respond event in the XML Server pro gram is triggered any time
so meo ne requests a do c ument using the fo llo wing URL:
http://Athena/VB6DB22/VB6DB22.ASP?wci=GetCustomer
This URL po ints to a c o mputer c alled Athena and lo o ks in the VB6DB22 direc to ry
fo r the file c alled VB6DB22.ASP. It passes the wci=GetCustomer parameter to the
file, whic h will trigger the GetCustomer_Respond event in the IIS Applic atio n (see
Listing 22-5).
Listing 22-5: The GetCustomer_Respond event in XM L Server
Private Sub GetCustomer_Respond()
Dim attr As IXMLDOMAttribute
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
el As IXMLDOMElement
nl As IXMLDOMNodeList
node As IXMLDOMElement
p As IXMLDOMProcessingInstruction
subnode As IXMLDOMElement
subsubnode As IXMLDOMElement
XMLReq As DOMDocument
XMLResp As DOMDocument
z() As Byte
Dim db As ADODB.Connection
Dim rs As ADODB.Recordset
z = Request.BinaryRead(10000)
Set XMLReq = New DOMDocument
XMLReq.loadXML StrConv(z, vbUnicode)
Set nl = XMLReq.getElementsByTagName(“CUSTOMER”)
Set XMLResp = New DOMDocument
Set p = XMLResp.createProcessingInstruction(“xml”, _
“version=””1.0”””)
XMLResp.appendChild p
Set node = XMLResp.createElement(“GETCUSTOMERINFO”)
XMLResp.appendChild node
Set db = New ADODB.Connection
db.Open _
“provider=sqloledb;data source=Athena;initial catalog=VB6DB”,
_
“sa”, “”
Set rs = New ADODB.Recordset
Set rs.ActiveConnection = db
For Each el In nl
rs.Source = “Select * From Customers Where CustomerId = “ & _
el.getAttribute(“CustomerId”)
rs.Open
If Not ((rs.BOF) And (rs.EOF)) Then
Set subnode = XMLResp.createElement(“CUSTOMER”)
Set attr = XMLResp.createAttribute(“CustomerId”)
attr.Text = rs(“CustomerId”).Value
subnode.Attributes.setNamedItem attr
Set attr = XMLResp.createAttribute(“Get”)
attr.Text = “OK”
subnode.Attributes.setNamedItem attr
Continued
493
494
Part V ✦ The Impact of XM L
Listing 22-5 (continued)
node.appendChild subnode
Set subsubnode = XMLResp.createElement(“NAME”)
subsubnode.Text = rs(“Name”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“STREET”)
subsubnode.Text = rs(“Street”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“CITY”)
subsubnode.Text = rs(“City”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“STATE”)
subsubnode.Text = rs(“State”).Value
subnode.appendChild subsubnode
Set subsubnode = XMLResp.createElement(“ZIP”)
subsubnode.Text = rs(“Zip”).Value
subnode.appendChild subsubnode
Else
Set subnode = XMLResp.createElement(“CUSTOMER”)
Set attr = XMLResp.createAttribute(“CustomerId”)
attr.Text = el.getAttribute(“CustomerId”)
subnode.Attributes.setNamedItem attr
Set attr = XMLResp.createAttribute(“Get”)
attr.Text = “Not found”
subnode.Attributes.setNamedItem attr
node.appendChild subnode
End If
rs.Close
Next el
XMLResp.Save Response
db.Close
Set XMLResp = Nothing
Set XMLReq = Nothing
Set rs = Nothing
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Set db = Nothing
End Sub
Preparing to respond to the request
After dec laring a who le lo t o f lo c al variables, I begin pro c essing by using the
Request.BinaryRead to get the input do c ument into a byte array. Next, I c reate
a new instanc e o f the DOMDocument o bjec t that will ho ld the request, and use the
loadXML metho d to build the do c ument o bjec t hierarc hy. No te that I used the
StrConv func tio n to c o nvert the ASCII enc o ded string into Unic o de befo re lo ading
it with the loadXML metho d. Finally, I use the getElementsByTagName metho d to
c reate a list o f all o f the CUSTOMER elements.
Then I c reate a new instanc e o f the respo nse do c ument ( XMLResp) and initialize it
with the standard XML versio n info rmatio n. Next, I will append a GETCUSTOMERINFO
o bjec t that will c o ntain the individual CUSTOMER elements that fo rm the respo nse.
In o rder to ac c ess the database, I c reate a new instanc e o f the ADODB.Connection
o bjec t and use the Open metho d to lo g o nto the database server. Then I c reate a
new instanc e o f the ADODB.Recordset o bjec t and set the ActiveConnection pro perty to the Connection o bjec t I just o pened.
Building the response
After all o f the prep wo rk, I use a For Each lo o p to ac c ess eac h CUSTOMER element
in the nodeList c o llec tio n. Using the info rmatio n fro m the CustomerId attribute, I
build a Select statement to retrieve info rmatio n abo ut the spec ified Custo merId
value and then o pen the Recordset o bjec t.
If the Recordset o bjec t c o ntains at least o ne rec o rd ( Not (rs.BOF And rs.EOF)
is True), I’ll c reate a new CUSTOMER element no de using the createElement
metho d, and set the CustomerId to the c urrent value o f Custo merId and the Get
attribute to OK.
Fo r eac h o f the fields that I want to return, I c reate a new element no de and assign
it the value fro m the c o rrespo nding database field. Then I add it to the CUSTOMER
element I c reated earlier. After I add all o f the elements, I c lo se the Recordset
o bjec t.
If the Select didn’t return any ro ws, I’ll c reate a CUSTOMER element with the
CustomerId and Get attributes as befo re, but rather than assigning the Get attribute a value o f OK, I’ll return “Not found”. Afterwards, I’ll c lo se the Recordset
o bjec t fo r the partic ular CUSTOMER element and repeat the For Each lo o p until
I’m o ut o f CUSTOMER elements to pro c ess.
495
496
Part V ✦ The Impact of XM L
Finally, I’ll use the XMLResp.Save metho d against the Response o bjec t. This will
auto matic ally take the XML do c ument sto red in the do c ument o bjec t mo del and
o utput the XML tags to the HTTP return stream. Onc e the do c ument is returned, I
c an c lo se the database c o nnec tio n and destro y the vario us o bjec ts I c reated while
pro c essing this request.
Updating Customer Information
Yo u’ve seen o ne way to handle a transac tio n using XML do c uments to c arry the
request and the respo nse. This is the basic way mo st XML data exc hanges will
o c c ur. It do esn’t matter if the do c ument exc hange returns info rmatio n o r perfo rms
a func tio n. As lo ng as the pro per info rmatio n is c o ntained in the do c ument, it really
do esn’t matter.
Ho wever, the GetCustomerInfo and GetCustomer_Respond ro utines are based o n
do c uments that are element-o riented. Eac h individual field is sto red in a separate
element. In the update pro c ess, I c ho o se to sto re eac h field as an element o f the
CUSTOMER element.
Defining the update XM L documents
When requesting an update, yo u need to inc lude all o f the fields that need to be
updated in the requesting do c ument. By using attributes instead o f elements, yo u
c an get a slightly smaller do c ument whic h pro bably wo n’t make muc h o f a differenc e in the lo ng run, but it do es result in a flatter hierarc hy whic h c an be easier to
pro c ess with yo ur applic atio n pro gram.
Listing 22-6 c o ntains a sample XML do c ument that wo uld be transmitted fro m the
XML c lient to the XML server to update a partic ular value. Eac h o f the fields to be
updated are sto red in a separate attribute, and the CustomerId attribute is used to
identify the c usto mer’s info rmatio n in the database.
Listing 22-6: An XM L document containing update
information
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
The do c ument to return the status o f the update is based o n the same do c ument
that was used to request the update (see Listing 22-7). The main differenc es are
that the individual attributes c o ntaining the data to be updated are no t returned,
while a new attribute c alled Update is added that will repo rt the status o f the
update.
Listing 22-7: An XM L document containing the results of the
update
Requesting an update
Clic king o n the Update Custo mer Info butto n will trigger the UpdateCustomerInfo
ro utine sho wn in Listing 22-8. This ro utine begins by c reating an o bjec t c alled
XMLReq, whic h will ho ld the XML request do c ument and insert the XML versio n pro c essing instruc tio n.
Listing 22-8: The UpdateCustomerInfo routine in XM L Client
Sub UpdateCustomerInfo()
Set XMLReq = CreateObject(“MSXML2.DOMDocument”)
Set p = XMLReq.createProcessingInstruction(“xml”,
“version=””1.0”””)
XMLReq.appendChild p
Set node = XMLReq.createElement(“UPDATECUSTOMERINFO”)
Set subnode = XMLReq.createElement(“CUSTOMER”)
subnode.setAttribute “CustomerId”, _
Document.AddressInfo.CustomerId.Value
subnode.setAttribute “Name”, Document.AddressInfo.Name.Value
subnode.setAttribute “Street”,
Document.AddressInfo.Street.Value
subnode.setAttribute “City”, Document.AddressInfo.City.Value
subnode.setAttribute “State”, Document.AddressInfo.State.Value
Continued
497
498
Part V ✦ The Impact of XM L
Listing 22-8 (continued)
subnode.setAttribute “Zip”, Document.AddressInfo.Zip.Value
node.appendChild subnode
XMLReq.appendChild node
MsgBox XMLReq.xml
set http=CreateObject(“MSXML2.XMLHTTP”)
http.Open “Post”, _
“http://athena/VB6DB22/VB6DB22.ASP?wci=UpdateCustomer”,
false
http.setRequestHeader “Content-Type”, “text/xml”
http.send XMLReq
Set XMLResp = CreateObject(“MSXML2.DOMDocument”)
XMLResp.LoadXML http.responsetext
MsgBox XMLResp.xml
End Sub
Next, I c reate the UPDATECUSTOMERINFO and CUSTOMER elements, whic h will ho ld
the request. Then I c an use the setAttribute metho d to add the vario us attribute
values to the CUSTOMER element. No te that the setAttribute metho d will auto matic ally c reate the XMLDOMAttribute o bjec t fo r the attribute if it do esn’t exist and
auto matic ally append it to the element. If the attribute o bjec t already exists, then
this metho d will merely update the value.
Befo re I send the do c ument to the server, I display it using a MsgBo x statement (see
Figure 22-6). Then I use the same tec hnique I used earlier to send the request to the
XML server and wait fo r its respo nse. When I rec eive the respo nse, I display the
respo nse to the user to let them kno w if the update was suc c essful o r no t (see
Figure 22-7).
Figure 22-6: Displaying the update request
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Figure 22-7: Displaying a successful update
Processing an update
On the server side, the UpdateCustomer_Respond event will b e triggered when
an XML do c ument arrives ( see Listing 22-9) . It uses the same pro c ess that the
GetCustomer_Respond metho d used to rec eive the XML do c ument, initialize the
return XML do c ument, and o pen a datab ase c o nnec tio n. I also selec t all o f the elements named CUSTOMER and save them in a nodeList o b jec t. Ho wever, fro m this
po int o n, the two ro utines differ signific antly.
Listing 22-9: The UpdateCustomer_Respond in XM L Server
Private Sub UpdateCustomer_Respond()
On Error Resume Next
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
Dim
attr As IXMLDOMAttribute
el As IXMLDOMElement
nl As IXMLDOMNodeList
node As IXMLDOMElement
p As IXMLDOMProcessingInstruction
parm As ADODB.Parameter
subnode As IXMLDOMElement
subsubnode As IXMLDOMElement
XMLReq As DOMDocument
XMLResp As DOMDocument
z() As Byte
Dim db As ADODB.Connection
Dim cmd As ADODB.Command
z = Request.BinaryRead(10000)
Set XMLReq = New DOMDocument
XMLReq.loadXML StrConv(z, vbUnicode)
Set nl = XMLReq.getElementsByTagName(“CUSTOMER”)
Set XMLResp = New DOMDocument
Continued
499
500
Part V ✦ The Impact of XM L
Listing 22-9 (continued)
Set p = XMLResp.createProcessingInstruction(“xml”, _
“version=””1.0”””)
XMLResp.appendChild p
Set node = XMLResp.createElement(“UPDATECUSTOMERINFO”)
XMLResp.appendChild node
Set db = New ADODB.Connection
db.Open _
“provider=sqloledb;data source=Athena;initial catalog=VB6DB”, _
“sa”, “”
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = db
cmd.CommandText = “Update Customers Set Name=?, Street=?, “ & _
“City=?, State=?, Zip=? Where CustomerId=?”
Set parm = cmd.CreateParameter(“Name”, adVarChar, adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Street”, adVarChar, _
adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“City”, adVarChar, adParamInput, 64)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“State”, adChar, adParamInput, 2)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“Zip”, adInteger, adParamInput, 4)
cmd.Parameters.Append parm
Set parm = cmd.CreateParameter(“CustomerId”, adInteger, _
adParamInput, 4)
cmd.Parameters.Append parm
For Each el In nl
cmd.Parameters(“CustomerId”).Value = _
el.getAttribute(“CustomerId”)
cmd.Parameters(“Name”).Value = el.getAttribute(“Name”)
cmd.Parameters(“Street”).Value = el.getAttribute(“Street”)
cmd.Parameters(“City”).Value = el.getAttribute(“City”)
cmd.Parameters(“State”).Value = el.getAttribute(“State”)
cmd.Parameters(“Zip”).Value = el.getAttribute(“Zip”)
db.Errors.Clear
cmd.Execute
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
Set subnode = XMLResp.createElement(“CUSTOMER”)
subnode.setAttribute “CustomerId”, _
cmd.Parameters(“CustomerId”).Value
If db.Errors.Count = 0 Then
subnode.setAttribute “Update”, “OK”
Else
subnode.setAttribute “Update”, db.Errors.Item(0).Description
End If
node.appendChild subnode
Next el
XMLResp.Save Response
Set XMLResp = Nothing
Set XMLReq = Nothing
db.Close
Set cmd = Nothing
Set db = Nothing
End Sub
I c ho se to c reate a parameterized Command o bjec t, whic h uses the Update statement to c hange the c o ntents o f the database. So , after c reating a new instanc e o f
the Command o bjec t, I c reate an Update statement listing eac h o f the fields I want to
update and assigning them a value o f questio n mark ( ?). The questio n mark is really
a plac eho lder that will be replac ed with the parameters asso c iated with the
Command o bjec t.
Then I c reate the Parameter o bjec ts fo r the Command o bjec t using the Create
Parameter metho d. I spec ify the name, data type, direc tio n, and length fo r eac h
parameter as I c reate it, then I Append it to the Command’s Parameters c o llec tio n.
No te that I c reate the Parameter o bjec ts in the same o rder that the questio n marks
appear. This is very impo rtant, sinc e the o nly way to asso c iate a parameter with the
statement is the o rder o f the parameters.
Onc e I’ve do ne all o f this setup wo rk, I’m ready to use a For Each lo o p to pro c ess
the list o f CUSTOMER elements. I use the getAttribute metho d to return the value
o f eac h o f the attributes fro m the XML request do c ument and save it as the value in
the c o rrespo nding Parameter o bjec t.
501
502
Part V ✦ The Impact of XM L
After defining the parameters, I clear the Connection object’s Errors collection and
Execute the command. Then I create the CUSTOMER element in the return document
and set the CustomerId property. If there were no database errors ( db.Errors.
Count = 0), I’ll set the Get attribute to OK; otherwise, I’ll set the Get attribute to
the Description property from the first element in the Errors collection.
No w I Append the CUSTOMER element to the XMLResp do c ument and retrieve the
next no de in the nodeList o bjec t. This pro c ess will c o ntinue until all o f the elements in the nodeList o bjec t have been pro c essed. I end the ro utine by saving
the XMLResp o bjec t to the Response stream, c lo sing the database c o nnec tio n
and destro ying the o bjec ts I used in this ro utine.
Thoughts about Programming XM L Documents
Without XML at your disposal, getting inform ation across the Web program m atically can be
difficult. You have to build com plicated program s that w ill dow nload a Web page containing the inform ation you w ant, and then try to parse it looking for the proper value. In addition, you have to update your program each tim e som eone updates the form at of the Web
page. How ever, XML offers an easier solution.
Using XML it is reasonable to build a pair of applications that com m unicate w ith each other
via the Internet using XML docum ents. The client program m ay be a traditional Visual Basic
program , or perhaps a JavaScript-based Web page, that generates an XML docum ent containing a request for inform ation. This request is then passed to a Web server, w hich
receives the XML docum ent, decodes it, and returns the data to the client program . Finally,
the client program extracts the inform ation it w ants from the return XML docum ent.
The nice thing about this approach is that you can use any tools you w ant on the client and
the server side. The only issue is that both program s m ust agree on the elem ents in the
XML docum ents that are exchanged. But as long as XML is used in the m iddle, the details of
the program s on each side aren’t im portant.
The program s can be coded in Visual Basic, VBScript, Java, C+ + , or even COBOL for that
m atter. They can run on Window s 2000 Server, Solaris, Linux, or OS/ 390. The point is, as
long as the XML is properly constructed, you have a vendor-independent solution.
You should consider the application I built here m erely as a toy to explore w hat you can do
w ith a little XML, HTML, and a Visual Basic program . I’m not saying that you should run out
and convert all of your applications to XML anytim e you need to pass inform ation. How ever,
XML is the w ave of the future, and anything you can do now to learn m ore about how to
use it w ill m ake your life easier in the future.
One of the problem s w ith m essage queues is that you need a w ay to pass inform ation
betw een the client application and the transaction server. While you can pass persisted
objects back and forth, they can be a pain to develop and debug. Since XML is hum an readable, it is easier to debug (trust m e —debugging a COM+ based m essage queue application
can be a real nightm are) w ithout losing any of the flexibility of objects it w ould replace.
Chapter 22 ✦ Integrating XM L with Internet Information Server Applications
You could easily com bine tools such as an IIS Application, COM+ transactions, m essage
queues, and XML to build a com plex, high-perform ance application that accepts vendorneutral requests coded in XML. This allow s you to develop clients for different platform s,
including such operating system s as Linux, Solaris, Macintosh, and even the occasional
OS/ 390 IBM m ainfram e.
Summary
In this c hapter yo u learned:
✦ ho w to design XML do c uments to request and rec eive info rmatio n fro m a
Web server.
✦ ho w to build an IIS Applic atio n that sends an XML request to a Web server.
✦ ho w to build an IIS Applic atio n to parse an XML do c ument.
✦ ho w to update a database using an XML do c ument.
✦
✦
✦
503