| Summary: | The Curl® language provides support for requests
for Web services using SOAP 1.1 over HTTP. This includes:
- automatic mapping from XML Schema simple types to Curl language
types
- the creation of Curl language descriptors
corresponding to SOAP remote procedure calls (RPCs)
- a straightforward way to define your own
marshaling and unmarshaling of XML types, and to register
those mappings
- a mapping from SOAP faults to Curl language exceptions
Note: There is a more complete and full featured SOAP implementation
in the Curl® WSDK. It includes full
support for almost all SOAP data types, support for
references, asynchronous SOAP calls and automatic code
generation from WSDL files. See the Curl web site for more information
about the Curl WSDK. |
Adding access to Web services to your applet written in the Curl
language is straightforward via the SOAP (Simple Object Access
Protocol) interface, contained in the
CURL.XML.SOAP
package. Suppose, for example, that you have an applet that does
some statistical analysis of stock prices. The analytic algorithms
run locally on the client machine, but it is necessary
periodically to go to a Web site to get current data for
analysis. For that, you need to add code to your applet that sends
a request for information to the Web service and handles the
returning data.
SOAP is an XML-based protocol for the exchange of information in a
distributed environment. You add SOAP remote procedure calls
(RPCs) to an applet written in the Curl language using the
Soap-1-1-HttpOperation class to describe the operation and the
Soap-1-1-StandardArgumentDescriptor class to define its
input and output arguments.
The runtime supports SOAP over HTTP by automatically converting
many XML Schema built-in data types to Curl language types. In
addition, there is support for creating and registering the
marshalers and unmarshalers needed to convert between Curl
language types and other XML types.
A. To use the Curl language to call a SOAP service over HTTP, follow
these steps:
- Locate the necessary information about the interface of a
SOAP service. This includes its URL, the value of the
SOAPAction HTTP header, the operation name, and the names and
types of its input and output arguments. This information may
be available from a Web Service Description Language (WSDL)
file or in some other form.
- Since the types of the arguments will be XML types, they
need to be mapped into Curl language types. The runtime supplies
some mappings between XML types and Curl language types, and in
addition gives you the means to supply your own mappings. If
all of the types of the input and output arguments are
included in the runtime-supplied mappings, there is no need to
supply your own mappings. For the case where you do need to
create such mappings, see Part B below.
- From the information in Steps 1 and 2, initialize an
instance of Soap-1-1-HttpOperation and instances
of Soap-1-1-StandardArgumentDescriptors. You create one
instance of a Soap-1-1-StandardArgumentDescriptor for each
input and output argument.
- Call the SOAP service using the call method on the
instance of Soap-1-1-HttpOperation you initialized in
the previous step.
B. In the case referred to in Step 2 above where the arguments are
of types that are not mapped automatically, you need to supply
your own mappings. To do this, for each such mapping between an
XML type and Curl language type:
- Identify the existing Curl language type or create a new Curl language type
you want to map the XML type to or from. See Data Types for details on
existing Curl language types.
- Write a marshaler or unmarshaler for the mapping. For input
arguments, you must supply a marshaler that converts values of
the Curl language type to values of the XML type. For output arguments,
you will need an unmarshaler that converts values of an XML
type to values of a Curl language type.
In addition, before calling a SOAP service that requires
user-supplied mappings: - Create an instance of XMLCurlMappingRegistry.
- Call the map-types method on the instance of
XMLCurlMappingRegistry for each mapping.
- Include the instance of XMLCurlMappingRegistry as
the value of the registry keyword argument in the
Soap-1-1-HttpOperation.call method.
These steps are explained in greater detail below.
Note: To use the SOAP interface, you need to import the
CURL.XML.SOAP package into your applet; include the
statement:
{import * from CURL.XML.SOAP}
in any applet that will use the classes in this package.
Consider the following WSDL (Web Service Description Language; see
www.w3.org/TR/wsdl for more about WSDL) file describing the
interface to a weather Web service; the service takes as input a
zip code and returns the temperature in that zip code's location.
Here is an example of a WSDL file describing a Web service.
<definitions name="TemperatureService"
targetNamespace="http://www.xmethods.net/sd/TemperatureService.wsdl">
<message name="getTempRequest">
<part name="zipcode" type="xsd:string"/>
</message>
<message name="getTempResponse">
<part name="return" type="xsd:float"/>
</message>
<portType name="TemperaturePortType">
<operation name="getTemp">
<input message="tns:getTempRequest"/>
<output message="tns:getTempResponse"/>
</operation>
</portType>
<binding name="TemperatureBinding" type="tns:TemperaturePortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getTemp">
<soap:operation soapAction=""/>
<input>
<soap:body use="encoded" namespace="urn:xmethods-Temperature-Demo" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded" namespace="urn:xmethods-Temperature-Demo" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="TemperatureService">
<documentation>
Returns current temperature in a given U.S. zipcode
</documentation>
<port name="TemperaturePort" binding="tns:TemperatureBinding">
<soap:address location="http://services.xmethods.net:80/soap/servlet/rpcrouter"/>
</port>
</service>
</definitions>
The process of finding the various pieces of information contained
in the WSDL, or an equivalent Web service description, consists
mainly in identifying: the name of the operation, any input
arguments, and any output arguments. Since elements are nested,
delimited by <element> <\element>, you will need to
search inside some elements to find others.
The default constructor for
Soap-1-1-HttpOperation has
these arguments:
- operation: The name of the SOAP operation.
- address: The HTTP address for the SOAP operation.
- soap-action: The value of the HTTP SOAPAction
header.
- input-arguments: The input arguments of the SOAP
operation.
- output-arguments: The output arguments of the
SOAP operation.
The following sections explain how to extract values for them from
the Web service description.
Contained within the
binding element is an
operation element. The
operation element has a
name attribute. Contained within the
operation element is
a
body element. The namespace of the
body element
is
"http://schemas.xmlsoap.org/wsdl/soap/". The
body element has a
namespace attribute. The
operation argument in the
Soap-1-1-HttpOperation is
XMLName, whose namespace is the value of the
namespace attribute of the
body element and whose
local-name is the value of the
name attribute of the
operation element.
In the WSDL file above, the value of the
namespace
attribute of the
body element is
"urn:xmethods-Temperature", and the value of the
name attribute of the
operation element is
"getTemp". So the value of the
operation argument in
the
Soap-1-1-HttpOperation is
{new XMLName,
"urn:xmethods-Temperature", "getTemp"}.
Locate the
port element corresponding to the
binding element referred to above. The
port element is
contained within a
service element. Locate the
address element contained in the
port element. The
namespace of the
address element is
"http://schemas.xmlsoap.org/wsdl/soap/". The
address
argument in the
Soap-1-1-HttpOperation constructor is the
value of the
location attribute in the
address
element.
In the WSDL file shown above, the value of the
location
attribute in the
address element is
"http://services.xmethods.net:80/soap/servlet/rpcrouter". This
is the value for the
address argument in the
Soap-1-1-HttpOperation constructor.
Contained in the
operation element with the
name
attribute is an
operation element. This
operation
element has the namespace
"http://schemas.xmlsoap.org/wsdl/soap/". The
soap-action argument in the
Soap-1-1-HttpOperation
constructor is the value of the
soapAction attribute in
the
operation element.
In the WSDL file above, the value of the
soapAction
attribute of the
operation element is
"" (the
empty string). So the value of the
soap-action argument
in the
Soap-1-1-HttpOperation is
"".
Translating the input and output argument information from the
WSDL file can be straightforward or complicated, depending on how
the WSDL file is written and the complexity of the arguments. We
will describe the straightforward case, as exemplified in the WSDL
shown above.
Locate the operation element where we found the operation
name above. It is contained in a binding element that has
a type attribute. The value of the type attribute
references a portType element. The value of the name attribute of the portType element will match the
value of the type attribute of the binding
element.
Now locate the matching operation element contained in the
portType element. Along with the operation element
will be an input element and an output element.
Both the input element and the output element have
message attributes. The value of each message
attribute references a message element. The value of the
name attribute of the message element will be the
same as the value of the message attribute of the input element or output element. The message
element describes the input or output arguments, depending on
whether it is referenced by an input or output
element.
Each part element corresponds to an argument. The message
corresponding to "getTemp"'s input arguments is "getTempRequest", and the message corresponding to "getTemp"'s output arguments is "getTempResponse". The
"getTempRequest" message contains one part
element, so the "getTemp" operation has just one input
argument.
The default constructor for
Soap-1-1-StandardArgumentDescriptor
has these arguments:
- name: The argument name.
- xml-type: The XML type of the argument.
- curl-type: The Curl type of the argument.
- encoding-style: An optional keyword argument
that allows you to specify the serialization rules to use for
the argument. The default value is the SOAP 1.1 serialization
rules.
The following paragraphs explain how to extract values for them
from the Web service description.
The
name argument of the
Soap-1-1-StandardArgumentDescriptor constructor is the value of the
name attribute of the
part element. For the
part element in
"getTempRequest", the value of the
name attribute is
"zipcode". Since
"zipcode" is
not namespace qualified, the value of the
name argument
to the
Soap-1-1-StandardArgumentDescriptor is
{new
XMLName, "", "zipcode"}.
The
xml-type argument of the
Soap-1-1-StandardArgumentDescriptor is the value of the
type
attribute of the
part element. For the
part
element in
"getTempRequest", the value of the
type
attribute is
"xsd:string", which is namespace
qualified. The namespace corresponding to the namespace prefix
"xsd" is
"http://www.w3.org/2001/XMLSchema". So
the value of the
xml-type argument of the
Soap-1-1-StandardArgumentDescriptor constructor is
{new XMLName,
"http://www.w3.org/2001/XMLSchema", "string"}.
We can accept the default value for the encoding-style
argument; in this case there is no need to specify a different
value.
Now that we have the various pieces, we need to instantiate the
Soap-1-1-HttpOperation and
Soap-1-1-StandardArgumentDescriptor classes, we can put all the operation
components together in a Curl applet. The Curl language signature
corresponding to the operation declared in the WSDL file shown
above is:
{define-proc {getTemp zipcode:String}:float}
The procedure getTemp will be defined in the descriptors
you create: the input and output arguments, and the SOAP operation
being requested. Here are the argument descriptors and the SOAP
operation for the request shown above, as defined in the Curl
language:
{import * from CURL.XML.SOAP}
{let xsd:String = "http://www.w3.org/2001/XMLSchema"}
{let xsi:String = "http://www.w3.org/2001/XMLSchema-instance"}
|| One input argument named "zipcode" of type "string"
|| corresponding to Curl language type String.
{let input-arguments:{Array-of Soap-1-1-ArgumentDescriptor} =
{{Array-of Soap-1-1-ArgumentDescriptor}
{Soap-1-1-StandardArgumentDescriptor
{XMLName "", "zipcode"},
{XMLName xsd, "string"},
String
}
}
}
|| One output argument named "return" of XML type float
|| corresponding to Curl language type float.
{let output-arguments:{Array-of Soap-1-1-ArgumentDescriptor} =
{{Array-of Soap-1-1-ArgumentDescriptor}
{Soap-1-1-StandardArgumentDescriptor
{XMLName "", "return"},
{XMLName xsd, "float"},
float
}
}
}
|| The operation descriptor.
{let get-temp:Soap-1-1-HttpOperation =
{Soap-1-1-HttpOperation
|| operation name
{XMLName "urn:xmethods-Temperature-Demo", "getTemp"},
|| url
{url "http://services.xmethods.net:80/soap/servlet/rpcrouter" },
|| SOAPAction value in HTTP headers
"",
input-arguments,
output-arguments,
include-type-attribute? = true, || ###
xsi = xsi || ###
}
}
{let result = {get-temp.call trace?= true, "02142"}}
{value result[0]}
Once you have defined the SOAP operation and specified its input
and output arguments, you can add the following SOAP RPC to your
Curl applet to request the service:
|| The actual SOAP call.
{let anys:{Array-of any}={get-temp.call "01915"}}
The output arguments of a SOAP RPC are returned in an
Array-of any. In this example, the SOAP RPC returns a single
output argument of type float. So
anys[0] contains the
result, a float representing a temperature.
When you are defining the arguments to your SOAP call, most of the
common XML built-in data types are converted for you to and from
the corresponding Curl language data types. Other XML types must be
marshaled and unmarshaled manually; see
Writing Your Own Marshalers and
Unmarshalers for details.
The following table shows the supplied mapping between XML
primitive and derived data types and Curl language data types.
| XML Type | Curl Language Type |
| string | String |
| boolean | bool |
| float | float |
| double | double |
| base64Binary | ByteVec |
| long | int64 |
| int | int32 |
| short | int16 |
| byte | int8 |
| unsignedShort | uint16 |
| unsignedByte | uint8 |
In addition, the Curl language SOAP support can handle the mapping
of array arguments. See the API Reference Manual entry for
Soap-1-1-ArrayArgumentDescriptor for details.
For the XML types (for example, struct) for which
conversions to and from Curl language types are not provided, you
will need to write your own marshalers and unmarshalers (also
called serializers and deserializers). The following sections show
how this is done.
The following example calls a SOAP operation named
"calculateExchangeRate", which takes one input argument of XML
type ConvertMessage, which is a struct composed of three
fields: a string, a double, and a string. This input argument
contains the name of a currency, an amount in that currency, and
the name of a currency to convert to. The operation
"calculateExchangeRate" returns a single result of XML type
double, which is the corresponding amount in the second currency.
Here is an instance of the XML type ConvertMessage:
<currency>NLG</currency>
<amount>1.00000000000000000E+002</amount>
<toCurrency>DEM</toCurrency>
Here is the Curl language class corresponding to the XML type
ConvertMessage; note that we have given the Curl language class
the same name as the XML type's, which is not necessary.
{define-class public ConvertMessage
field public currency:String
field public amount:double
field public to-currency:String
{constructor public {default
currency:String,
amount:double,
to-currency:String
}
set self.currency=currency
set self.amount=amount
set self.to-currency=to-currency
}
}
This code for marshaling a struct uses a marshaler helper,
which marshals one field of the struct, and the marshaler
itself, which puts all the pieces together:
|| marshaler helper -- marshals a field of a struct.
{define-proc public {marshaler-helper
mapper:XMLCurlMappingRegistry,
encoding-style:String,
xos:XMLOutputStream,
element-name:XMLName,
content-xml-type:XMLName,
content-curl-type:Type,
content-value:any,
include-type-attribute?:bool,
xsi:String
}:void
{xos.write-one {new XMLStartElement, element-name}}
{mapper.marshal
encoding-style,
content-value asa content-curl-type,
content-curl-type,
content-xml-type,
xos,
include-type-attribute?,
xsi
}
{xos.write-one {new XMLEndElement}}
{return}
}
|| converts Curl language value to XML for ConvertMessage type
{define-proc public {convert-message-marshaler
mapper:XMLCurlMappingRegistry,
encoding-style:String,
value:any,
xos:XMLOutputStream,
include-type-attribute?:bool,
xsi:String
}:void
let cm:ConvertMessage = value asa ConvertMessage
{marshaler-helper
mapper,
encoding-style,
xos,
{new XMLName, "", "currency"},
{new XMLName, "", "string"},
String,
cm.currency,
include-type-attribute?,
xsi
}
{marshaler-helper
mapper,
encoding-style,
xos,
{new XMLName, "", "amount"},
{new XMLName, "", "double"},
double,
cm.amount,
include-type-attribute?,
xsi
}
{marshaler-helper
mapper,
encoding-style,
xos,
{new XMLName, "", "toCurrency"},
{new XMLName, "", "string"},
String,
cm.to-currency,
include-type-attribute?,
xsi
}
{return}
}
The following code is an example of a custom unmarshaler. The
operation, named "translate", takes an input argument of XML type
string containing a hostname and does a DNS lookup on the
hostname. It returns a struct called InternetAddress,
containing the IP address and the hostname. Both fields of the
struct are of XML type string.
Here is an instance of the XML type InternetAddress:
<IP>167.216.248.234</IP>
<Hostname>www.curl.com</Hostname>
Here is the Curl language class corresponding to the XML type
InternetAddress; note that we have given the Curl language class
the same name as the XML type's, which is not necessary.
{define-class public InternetAddress
field public ip:String
field public hostname:String
{constructor public {default ip:String, hostname:String}
set self.ip=ip
set self.hostname=hostname
}
}
As is the case for the marshaler, there is an unmarshaler helper,
which unmarshals one field, and the unmarshaler itself, which puts
the pieces together:
|| This procedure unmarshals a filed of a struct
{define-proc public {unmarshaler-helper
mapper:XMLCurlMappingRegistry,
encoding-style:String,
input:XMLInputStream,
element-name:XMLName,
content-xml-type:XMLName,
content-curl-type:Type
}:any
let xml-token:XMLToken={input.read-one}
{if {type-of xml-token} != XMLStartElement then
{error "expecting XMLStartElement"}
}
{if (xml-token asa XMLStartElement).element != element-name then
{error "element name mismatch"}
}
let return-value:any = {mapper.unmarshal
encoding-style,
content-curl-type,
content-xml-type,
input
}
set xml-token={input.read-one}
{if {type-of xml-token} != XMLEndElement then
{error "expecting XMLEndElement"}
}
{return return-value}
}
||Convert XML to Curl language for type InternetAddress
{define-proc public {internet-address-unmarshaler
mapper:XMLCurlMappingRegistry,
encoding-style:String,
input:XMLInputStream
}:any
let ip:any={unmarshaler-helper
mapper,
encoding-style,
input,
{new XMLName, "", "IP"},
{new XMLName, "", "string"},
String
}
let hostname:any={unmarshaler-helper
mapper,
encoding-style,
input,
{new XMLName, "", "Hostname"},
{new XMLName, "", "string"},
String
}
{return {new InternetAddress, (ip asa String), (hostname asa
String)
}
}
}
After you have created any marshalers and unmarshalers you need,
you can register the new type mappings. The process consists of:
initializing a type mapping registry, registering the marshaler or
unmarshaler, and including the
registry keyword argument
in the
Soap-1-1-HttpOperation.call. For the marshaler
in the example above, the code looks like this (an unmarshaler is
registered exactly the same way):
|| 1. create a type mapping registry
{let my-registry:XMLCurlMappingRegistry={new XMLCurlMappingRegistry}}
|| 2. register the marshaler for ConvertMessage
{my-registry.map-types
soap-encoding,
{new XMLName,
"",
"ConvertMessage"},
ConvertMessage,
convert-message-marshaler,
null
}
|| 3. the actual SOAP call
{let anys:#{Array-of any}={currency-converter.call
{new ConvertMessage, "NLG", 100.0, "DEM"},
registry=my-registry
}
}
Most of the problems that arise when you are using SOAP RPCs
return Curl language exceptions; that is, the SOAP faults are translated to
Curl language exception types. Here are some suggestions about
where to look for errors when things are not working as you
expected:
| What Went Wrong | Why It Happened |
| The Soap-1-1-HttpOperation.call threw an
HttpException. | This happens when the response status from an HTTP request
containing a SOAP message is not OK (200) and the response
body is empty or does not contain a SOAP message. The
response status included in the HttpException will
provide more information on the nature of the error. It may be
that the Web server is not available, or that the address field in the Soap-1-1-HttpOperation was not
set correctly. |
| The Soap-1-1-HttpOperation.call threw a
Soap-1-1-FaultException. | This happens when the response message from the SOAP service
contains a SOAP fault element. A
Soap-1-1-FaultException displays the fault code and
fault string sub-elements of the SOAP fault element. The fault
string is intended to provide a human-readable explanation of
the fault. SOAP 1.1 defines four possible values for the fault
code. They are:
- "VersionMismatch"—The SOAP service found an
invalid namespace for the SOAP envelope element. This may
indicate that the service is not a SOAP 1.1 service.
- "MustUnderstand"—The request contained a SOAP
header sub-element with the mustUnderstand
attribute, and the SOAP service could not understand
or comply.
- "Client"—The message in the request was
incorrectly formed or did not contain the appropriate
information to succeed.
- "Server"—The request could not be processed for
reasons not directly attributable to the contents of the
message but rather to the processing of the message.
Note: A Soap-1-1-FaultException displays the fault
code and the fault string, but not the rest of SOAP fault
element. Most SOAP fault elements contain a detail
sub-element. Set the trace? argument on the
Soap-1-1-HttpOperation.call to true to
display the full response in the output log and view
additional sub-elements of the SOAP fault. |
The Soap-1-1-HttpOperation.call gave an error of the
form:
"unable to marshal value of Curl language type {type-of value}
to XML type xml-type using encoding style encoding-style" | This error indicates that a mapping could not be found to
marshal a value of a Curl language type to an XML type. The runtime
provides a number of mappings, and you may write
custom marshalers (serializers) and register your own
mappings. This error indicates that a mapping could not be
found in either the user-supplied registry (if a user-supplied
registry is provided in the call via the registry
keyword argument) or the runtime-supplied registry. The
cause of this error might be that a
Soap-1-1-StandardArgumentDescriptor has been incorrectly
specified. |
The Soap-1-1-HttpOperation.call gave an error of the
form:
"unable to unmarshal value of XML type xml-type to Curl
type curl-type using encoding style encoding-style" | This error indicates a mapping could not be found to
unmarshal a value of an XML type to a Curl language type. The runtime
provides a number of mappings, and you may write
custom unmarshalers (deserializers) and register your own
mappings. This error indicates that a mapping could not
be found in either the user-supplied registry (if a
user-supplied registry is provided in the call via the
registry keyword argument) or the runtime-supplied
registry. The cause of this error might be that a
Soap-1-1-StandardArgumentDescriptor has been incorrectly
specified. |
| A conversion error occurred in the marshaling or
unmarshaling during a Soap-1-1-HttpOperation.call. | Possible causes include: an input argument supplied in the
call is of an incorrect type; a
Soap-1-1-StandardArgumentDescriptor has been incorrectly
specified; or there is an error in a user-supplied marshaler
or unmarshaler. |
| The Soap-1-1-HttpOperation.call gave an error
parsing the return message. | One possible cause is an error in a user-supplied marshaler
or unmarshaler. |
The
trace? keyword argument on
Soap-1-1-HttpOperation.call, when set to
true, can be
used to examine the body of the HTTP request containing the SOAP
RPC and the body of the HTTP response. For example, when a
Soap-1-1-FaultException exception is returned, you can
use this to display all the sub-elements of the SOAP fault.
This argument is described in the API Reference Manual
entry for
Soap-1-1-HttpOperation.call.
The SOAP interface also supports the reading and writing of SOAP
headers; the following example makes a call to a Web service that
echoes SOAP headers. This SOAP operation named "echoVoid" takes no
arguments and returns no result, it simply echoes the SOAP headers
used in the call.
{import * from CURL.XML.SOAP}
{let xsd:String = "http://www.w3.org/2001/XMLSchema"}
|| 0 input arguments
{let input-arguments:{Array-of Soap-1-1-ArgumentDescriptor}=
{new {Array-of Soap-1-1-ArgumentDescriptor}}
}
|| 0 output arguments
{let output-arguments:{Array-of Soap-1-1-ArgumentDescriptor}=
{new {Array-of Soap-1-1-ArgumentDescriptor}}
}
|| construct a header as an array of XMLToken
{let input-headers:{Array-of XMLToken}={new {Array-of XMLToken}}}
|| the header element is "echoMeStringRequest" containing a string
{input-headers.append {new XMLStartElement,
{new XMLName,
"http://soapinterop.org/echoheader/",
"echoMeStringRequest"}
}
}
{input-headers.append {new XMLCharacters, "Hello, Header"}}
{input-headers.append {new XMLEndElement}}
|| operation descriptor
{let echo-void:Soap-1-1-HttpOperation=
{new Soap-1-1-HttpOperation,
|| operation name
{new XMLName,"http://soapinterop.org/", "echoVoid"},
|| url
|| {url "http://mssoapinterop.org/stk/InteropC.wsdl" },
{url "http://www.whitemesa.net/interop/std/echohdr"},
|| SOAPAction value
|| "urn:soapinterop",
"http://soapinterop.org/",
input-arguments,
output-arguments
}
}
|| the actual SOAP call -- headers are passed a value
|| of keyword argument
{let (anys:#{Array-of any}, return-headers:#{Array-of XMLToken})=
{echo-void.call headers=input-headers, trace?=true}
}
|| The output arguments are returned in array of anys
|| This soap call returns 0 arguments
{if anys.size !=0 then
{error "expected 0 return arguments, but got " & anys.size}
}
|| The headers are returned as array of XMLToken.
|| The header passed back should have the same contents
|| as the string passed in -- "Hello, Header"
{if return-headers.size < 4 then
{error "error in return headers"}
}
{if {type-of return-headers[0]} != XMLStartElement then
{error "expected first element of return headers to be
XMLStartElement"}
}
{if {type-of return-headers[1]} != XMLAttribute then
{error "expected first element of return headers to be
XMLAttribute"}
}
{type-switch return-headers[2]
case chars:XMLCharacters do
{output "content of return header element: " & chars.characters}
else
{error "expect XMLCharacters as second element of return headers"}
}
{if {type-of return-headers[3]} != XMLEndElement then
{error "expected first element of return headers to be
XMLEndElement"}
}
The HTTP requests initiated by SOAP calls are subject to the same
security checks as other HTTP requests. The restrictions are
described in the section on
Network Access Restrictions.
If your applets are accessing Web services provided by your own
organization, the security impact is minimal.
Copyright © 1998-2019 SCSK Corporation.
All rights reserved.
Curl, the Curl logo, Surge, and the Surge logo are trademarks of SCSK Corporation.
that are registered in the United States. Surge
Lab, the Surge Lab logo, and the Surge Lab Visual Layout Editor (VLE)
logo are trademarks of SCSK Corporation.