Section 21.7. XML and Web Services


21.7. XML and Web Services

Web services represent an important use for XML, and SOAP is a popular web service protocol that is entirely XML-based. In this section, I'll show you how to use the XMLHttpRequest object and XPath queries to make a simple SOAP request to a web service.

Example 21-14 is JavaScript code that constructs an XML document representing a SOAP request and uses XMLHttpRequest to send it to a web service. (The web service returns the conversion rate between the currencies of two countries.) The code then uses an XPath query to extract the result from the SOAP response returned by the server.

Before considering the code, here are some caveats. First, details on the SOAP protocol are beyond the scope of this chapter, and this example demonstrates a simple SOAP request and SOAP response without any attempt to explain the protocol or the XML format. Second, the example does not use Web Services Definition Language (WSDL) files to look up web service details. The server URL, method, and parameter name are all hardcoded into the sample code.

The third caveat is a big one. The use of web services from client-side JavaScript is severely constrained by the same-origin security policy (see Section 13.8.2.). Recall that the same-origin policy prevents client-side scripts from connecting to, or accessing data from, any host other than the one from which the document that contains the script was loaded. This means that JavaScript code for accessing a web service is typically useful only if it is hosted on the same server as the web service itself. Web service implementors may want to use JavaScript to provide a simple HTML-based interface to their services, but the same-origin policy precludes the widespread use of client-side JavaScript to aggregate the results of web services from across the Internet onto a single web page.

In order to run Example 21-14 in IE, you can relax the same-origin security policy. Select Tools Internet tab in the resulting dialog. Scroll through the list of security options to find one named Access data sources across domains. This option is usually (and should be) set to disabled. In order to run this example, change it to prompt.

To allow Example 21-14 to run in Firefox, the example includes a call to the Firefox-specific enablePrivilege( ) method. This call prompts the user to grant enhanced privileges to the script so that it can override the same-origin policy. This works when the example is run from a file: URL in the local filesystem but does not work if the example is downloaded from a web server (unless the script has been digitally signed, which is beyond the scope of this book).

With those caveats out of the way, let's move on to the code.

Example 21-14. Querying a web service with SOAP

 /**  * This function returns the exchange rate between the currencies of two  * countries. It determines the exchange rate by making a SOAP request to a  * demonstration web service hosted by XMethods (http://www.xmethods.net).  * The service is for demonstration only and is not guaranteed to be  * responsive, available, or to return accurate data. Please do not  * overload XMethod's servers by running this example too often.  * See http://www.xmethods.net/v2/demoguidelines.html  */ function getExchangeRate(country1, country2) {     // In Firefox, we must ask the user to grant the privileges we need to run.     // We need special privileges because we're talking to a web server other     // than the one that served the document that contains this script.        UniversalXPConnect     // allows us to make an XMLHttpRequest to the server, and     // UniversalBrowserRead allows us to look at its response.     // In IE, the user must instead enable "Access data sources across domains"     // in the Tools->Internet Options->Security dialog.     if (typeof netscape != "undefined") {         netscape.security.PrivilegeManager.                 enablePrivilege("UniversalXPConnect UniversalBrowserRead");     }     // Create an XMLHttpRequest to issue the SOAP request. This is a utility     // function defined in the last chapter.     var request = HTTP.newRequest( );     // We're going to be POSTing to this URL and want a synchronous response     request.open("POST", "http://services.xmethods.net/soap", false);     // Set some headers: the body of this POST request is XML     request.setRequestHeader("Content-Type", "text/xml");     // This header is a required part of the SOAP protocol     request.setRequestHeader("SOAPAction", '""');     // Now send an XML-formatted SOAP request to the server     request.send(         '<?xml version="1.0" encoding="UTF-8"?>' +         '<soap:Envelope' +         '  xmlns:ex="urn:xmethods-CurrencyExchange"' +         '  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"' +         '  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"' +         '  xmlns:xs="http://www.w3.org/2001/XMLSchema"' +         '  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' +         '   <soap:Body ' +         '     soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'+         '      <ex:getRate>' +         '         <country1 xsi:type="xs:string">' + country1 + '</country1>' +         '         <country2 xsi:type="xs:string">' + country2 + '</country2>' +         '      </ex:getRate>' +         '   </soap:Body>' +         '</soap:Envelope>'         );     // If we got an HTTP error, throw an exception     if (request.status != 200) throw request.statusText;     // This XPath query gets us the <getRateResponse> element from the document     var query = "/s:Envelope/s:Body/ex:getRateResponse";     // This object defines the namespaces used in the query     var namespaceMapping = {         s:  "http://schemas.xmlsoap.org/soap/envelope/",  // SOAP namespace         ex: "urn:xmethods-CurrencyExchange" // the service-specific namespace     };     // Extract the <getRateResponse> element from the response document     var responseNode=XML.getNode(request.responseXML, query, namespaceMapping);     // The actual result is contained in a text node within a <Result> node     // within the <getRateReponse>     return responseNode.firstChild.firstChild.nodeValue; } 




JavaScript. The Definitive Guide
JavaScript: The Definitive Guide
ISBN: 0596101996
EAN: 2147483647
Year: 2004
Pages: 767

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