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 peri-o dic rate peri-o r fperi-o llperi-o wing mperi-o rtgage rates? Maybe yperi-o u want tperi-o 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 r-matio n. The fac t that yo u c an leverage existing HTTP tec h-no lo gies, suc h as Web servers and Web develo pment to o ls, makes it easier to build these applic atio ns.
2 2
2 2
✦
✦
✦
✦
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 r-matio n abo ut a c usto mer and updating info rr-matio n abo ut a c usto mer.Figure 22-1: Running the XM L 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 <head>, the <body>,and the <script>. While I’ve left the tags fo r <script>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
<html> <head>
<body>
<input type=”text” name=”City” size=”30” value=””> <input type=”text” name=”State” size=”2” value=””> <input type=”text” name=”Zip” size=”5” value=””> </td>
At the bo tto m o f the fo rm, I dec lared butto ns that will c all the GetCustomerInfo
and UpdateCustomerInfoVBSc ript ro utines. This is where the ac tual wo rk o f c o n-verting 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 GetCustomerInfosc ript ro utine takes the CustomerIdfield 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 u-ment defines the GETCUSTOMERINFOelement to identify the request. Within the GET-CUSTOMERINFOelement are o ne o r mo re CUSTOMERelements 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
<?xml version=”1.0”?> <GETCUSTOMERINFO>
<CUSTOMER CustomerId=”0”/> </GETCUSTOMERINFO>
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 CUSTOMERelement 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, Getwill c o ntain an erro r message.
Listing 22-3:
A sample response to the request for customer
information
<GETCUSTOMERINFO>
<NAME>
Dexter Valentine </NAME>
<STREET>
3250 Second Ave. </STREET>
<CITY>
San Francisco </CITY>
<STATE> CA </STATE> <ZIP>
94115 </ZIP> </CUSTOMER> </GETCUSTOMERINFO>
Requesting a customer
Pressing the Get Custo mer Info b utto n o n the Web page will trigger the
GetCustomerInfoVBSc ript ro utine in the <script>sec tio n o f the HTML do c u-ment ( 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
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
End If
End Sub
The format’s changed to protect the guilty: I adm it it. I’ve reform atted all of the HTM L 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 GetCustomerInforo utine begins by c reating a DOMDocumento bjec t c alled
XMLReqto 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 Dimand Setstatements to c reate the o bjec t, bec ause VBSc ript c an’t ref-erenc 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 CreateObjectfunc tio n.
After c reating the base do c ument, I add the <?xml version=”1.0”?>element by using the createProcessingInstructionand appendChildmetho 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 GETCUSTOMERINFOelement that really defines this do c ument by using the createElementmetho d. This returns an o bjec t referenc e to an XMLDOMElemento bjec t, whic h I save in the variable c alled
node. Then I c reate ano ther XMLDOMElemento bjec t fo r CUSTOMERin the variable
subnode. I use the setAttributemetho d to c reate the CustomerIdattribute with the value fro m the CustomerIdfield in the fo rm. Then I c o nnec t the subnodeo bjec t to the nodeo bjec t by using the node.appendChildmetho d. Next, I use the
XMLReq.appendChildmetho d to link the nodeo 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 GET-CUSTOMERINFOelement 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 MsgBoxstatement ( see Figure 22-2) and the
XMLReq.xmlmetho 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.
Figure 22-2: View ing the XM L GETCUSTOM ERINFO
request docum ent
Sending the request document
In the next sec tio n o f the ro utine, I c reate an XMLHttpo bjec t c alled httpto perfo rm the ac tual data transfer. After c reating http, I use the openmetho 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 asyn-c hro no us transfer. This means that the sendmetho 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 onreadystatechangeevent to determine when the respo nse do c ument has been rec eived.
Befo re I send the do c ument, I use the setRequestHeadermetho 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 b o th sides are expec ting XML do c uments to b e transferred, it may b e impo rtant in o ther situatio ns where different pro c essing paths may b e taken depending o n the do c ument type.
When the c o de reac hes the sendmetho 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 XM L docum ent
Do I really want to do this?:Changing the security level in your brow ser to allow you to use the sendm 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 sendmetho 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
metho d to c reate the do c ument fro m the http.responsetextpro perty and then use the MsgBoxstatement to display the respo nse do c ument to the user (see Figure 22-4).
Figure 22-4: View ing the GETCUSTOM ERINFO 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 hierar-c hy to find the CUSTOMERelement 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 nodeListo bjec t that c o ntains all o f the CUSTOMER
elements using the getElementsByTagNamemetho d. Sinc e it is po ssible that the
nodeListo bjec t may have mo re than o ne CUSTOMERelement, I’ll set the variable i
to zero and use a Do Whilelo 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 iwill 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 nodeListo bjec t is a zero -based c o llec tio n, so if it c o n-tains o nly o ne element, the element will have an index value o f zero while the c o l-lec tio n has a lengtho f o ne.)
Next, I c hec k the value o f ito 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 nodeListo bjec t by searc hing fo r a partic ular ele-ment 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 CUSTOMERelement, I c an safely ac c ess the first value in the returned nodeListsinc e I kno w it must be the o nly ele-ment in the list. Then I c an use the textpro perty to extrac t the value o f the
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 Postmetho 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 u-ment with the appro priate respo nse.
The GetCustomer_Respondevent 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 Athenaand lo o ks in the VB6DB22direc to ry fo r the file c alled VB6DB22.ASP. It passes the wci=GetCustomerparameter to the file, whic h will trigger the GetCustomer_Respondevent 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 el As IXMLDOMElement 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
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 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.BinaryReadto get the input do c ument into a byte array. Next, I c reate a new instanc e o f the DOMDocumento bjec t that will ho ld the request, and use the
loadXMLmetho d to build the do c ument o bjec t hierarc hy. No te that I used the
StrConvfunc tio n to c o nvert the ASCII enc o ded string into Unic o de befo re lo ading it with the loadXMLmetho d. Finally, I use the getElementsByTagNamemetho d to c reate a list o f all o f the CUSTOMERelements.
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 CUSTOMERelements 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 Openmetho d to lo g o nto the database server. Then I c reate a new instanc e o f the ADODB.Recordseto bjec t and set the ActiveConnectionpro p-erty to the Connectiono bjec t I just o pened.
Building the response
After all o f the prep wo rk, I use a For Eachlo o p to ac c ess eac h CUSTOMERelement in the nodeListc o llec tio n. Using the info rmatio n fro m the CustomerIdattribute, I build a Se le ctstatement to retrieve info rmatio n abo ut the spec ified Custo merId value and then o pen the Recordseto bjec t.
If the Recordseto 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 CUSTOMERelement no de using the createElement
metho d, and set the CustomerIdto 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 Se le ctdidn’t return any ro ws, I’ll c reate a CUSTOMERelement with the
CustomerIdand Getattributes as befo re, but rather than assigning the Get attri-bute a value o f OK, I’ll return “Not found”. Afterwards, I’ll c lo se the Recordset
Finally, I’ll use the XMLResp.Savemetho d against the Responseo 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 GetCustomerInfoand GetCustomer_Respondro 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
CUSTOMERelement.
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 differ-enc 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 CustomerIdattribute 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
<?xml version=”1.0”?> <UPDATECUSTOMERINFO>
<CUSTOMER CustomerId=”0” Name=”Dexter Valentine” Street=”3250 Second Ave.” City=”San Francisco” State=”CA” Zip=”94115”/>
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 Updateis added that will repo rt the status o f the update.
Listing 22-7:
An XM L document containing the results of the
update
<?xml version=”1.0”?> <UPDATECUSTOMERINFO>
<CUSTOMER CustomerId=”0” Update=”OK”/> </UPDATECUSTOMERINFO>
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 instru-c 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
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 UPDATECUSTOMERINFOand CUSTOMERelements, whic h will ho ld the request. Then I c an use the setAttributemetho d to add the vario us attribute values to the CUSTOMERelement. No te that the setAttributemetho d will auto mat-ic ally c reate the XMLDOMAttributeo 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-7: Displaying a successful update
Processing an update
On the server side, the UpdateCustomer_Respondevent 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_Respondmetho 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 ele-ments named CUSTOMERand save them in a nodeListo 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 attr As IXMLDOMAttribute Dim el As IXMLDOMElement Dim nl As IXMLDOMNodeList Dim node As IXMLDOMElement
Dim p As IXMLDOMProcessingInstruction Dim parm As ADODB.Parameter
Dim subnode As IXMLDOMElement Dim subsubnode As IXMLDOMElement Dim XMLReq As DOMDocument
Dim XMLResp As DOMDocument Dim 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
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 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 Commando bjec t, whic h uses the Update state-ment to c hange the c o ntents o f the database. So , after c reating a new instanc e o f the Commando bjec t, I c reate an Updatestatement 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
Commando bjec t.
Then I c reate the Parametero bjec ts fo r the Commando bjec t using the Create Parametermetho 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 Appendit to the Command’s Parametersc o llec tio n. No te that I c reate the Parametero 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.
After defining the parameters, I clear the Connectiono bject’s Errorsco llectio n and
Executethe co mmand. Then I create the CUSTOMERelement in the return do cument and set the CustomerIdpro perty. If there were no database erro rs (db.Errors. Count = 0), I’ll set the Getattribute to OK; o therwise, I’ll set the Getattribute to the Descriptionpro perty fro m the first element in the Errorsco llectio n.
No w I Appendthe CUSTOMERelement to the XMLRespdo c ument and retrieve the next no de in the nodeListo b jec t. This pro c ess will c o ntinue until all o f the ele-ments in the nodeListo b jec t have b een pro c essed. I end the ro utine b y saving the XMLRespo b jec t to the Responsestream, c lo sing the datab ase c o nnec tio n and destro ying the o b jec ts I used in this ro utine.
Thoughts about Programming XM L Documents
Without XM L 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 contain-ing the inform ation you w ant, and then try to parse it lookcontain-ing for the proper value. In addi-tion, you have to update your program each tim e som eone updates the form at of the Web page. How ever, XM L offers an easier solution.
Using XM L it is reasonable to build a pair of applications that com m unicate w ith each other via the Internet using XM L docum ents. The client program m ay be a traditional Visual Basic program , or perhaps a JavaScript-based Web page, that generates an XM L docum ent con-taining a request for inform ation. This request is then passed to a Web server, w hich receives the XM L 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 XM L 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 XM L docum ents that are exchanged. But as long as XM L 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 XM L 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 XM L, HTM L, and a Visual Basic program . I’m not saying that you should run out and convert all of your applications to XM L anytim e you need to pass inform ation. How ever, XM L 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.
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.