5.2 XML Definitions
This chapter introduces the structure and mechanics of SOAP and SOAP messages. In practice, the majority of the work behind creating SOAP messages and
Because SOAP is by its very nature a more complex protocol than XML-RPC, it should be no surprise that the depth of the XML it uses is appropriately more complex. One of the key differences between parsing SOAP messages as opposed to XML-RPC is the need for support of XML namespaces. SOAP not only uses namespaces for their original purpose of mixing document-type elements, it also uses them to distinguish between different versions of the specification.
Another important factor in processing a typical SOAP message is that the specification requires the message contain no DTD declaration or processing instructions (which includes XML comments). This may limit the ability to apply other technologies, such as XSLT, to either the request or response messages. The current draft proposals for SOAP 1.2 allow processing instructions to be present but
Despite these minor differences, a SOAP message is still at its
5.2.1 The Basic Message Structure
In the simplest of terms, a SOAP message is made up of the following
Example 5-1 is a simple message with Envelope , Header , and Body . Example 5-1. A basic SOAP message
<
SOAP-ENV:Envelope
xmlns:SOAP-ENV=
"http://schemas.xmlsoap.org/soap/envelope/">
<
SOAP-ENV:Header
>
<auth:Authorize xmlns:auth=
"http://auth.xmlsoap.org/auth/">
<auth:type>user</auth:type>
<auth:name>soapclient</auth:name>
<auth:passwd>s0m3*th!ng</auth:passwd>
</auth:Authorize>
<
/SOAP-ENV:Header
>
<
SOAP-ENV:Body
>
<call:getQuote xmlns:call=
"http://bigtrade.com/soap/service/">
...detail of function call and data
</call:getQuote>
<
/SOAP-ENV:Body
>
<
/SOAP-ENV:Envelope
>
The message starts with the required Envelope tag. The tag is qualified as being in a namespace that is referenced by the URI http://schemas.xmlsoap.org/soap/envelope/ . This particular namespace is what identifies the message as being SOAP 1.1, so the declaration does double-duty, both declaring the prefix and identifying the SOAP version. The Header element is an optional part of the message. In this case it illustrates how a client might pass authentication credentials to the server. In a more complete example, there would likely be attributes in the Authorize tag that control how the server would respond if it did not understand what to do with the tag (discussed in more detail in the section Section 5.2.3). Here, it is enough to see how the child tags are required to be namespace-qualified as well, to set them apart from the SOAP-ENV space. Note that the child tags of Authorize use the same namespace as their parent. (We made up the namespace for the Authorize tag, despite the xmlsoap.org domain, so don't try to use it in your own programs!)
Because HTTP messages aren't encrypted, in practice you wouldn't send a password in the clear like this. The
Following the Header is the mandatory Body element. As with the header part of the message, the immediate child tag within Body is expected to have a separate namespace from that of the SOAP envelope. Of course, the authorization and the function call could have used the same namespace, but the getQuote tag would still have had to declare it. At this point, the earlier declaration made for Authorize has gone out of scope. The tag in the body of the message is the beginning of a common SOAP example, the stock trading-price quote. [1] The details of the call itself and the data within will be explained when we get to the Body element.
Because SOAP messages can become lengthy and complex, many of the examples through the rest of this book will be
5.2.2 The Envelope Tag: Declaring NamespacesIn Example 5-1, the Envelope tag was used only to declare the basic SOAP namespace. In fact, a tag may be used to declare as many namespaces as the application needs to define at a given point, and the start of the message is often the choice. Some frequently used namespaces that get in SOAP messages are listed in Table 5-1. The table also shows the labels that are consistently used to identify them throughout the book. Table 5-1. The most common namespaces
The
SOAP-ENV
and
SOAP-ENC
labels occur multiple times in the table because the namespace URI is also used to identify which version of the SOAP specification has been used for the message. In the working drafts for SOAP 1.2, we use the labels
env
and
enc
in place of
SOAP-ENV
and
SOAP-ENC
. The older labels are used by some toolkits and languages, regardless of the SOAP version. Within this and the chapters that follow, the
The SOAP-ENV label is familiar; it was used in Example 5-1. But what exactly is the SOAP-ENC label used to annotate? This label is used in the SOAP specification to define the namespace for the data encoding SOAP itself provides for convenience. Messages may often be able to express all data using these encodings, without having to use any XML Schema. Some messages may use multiple encodings. It isn't unusual to see a tag like that in Example 5-2, where several namespaces are declared at once. Example 5-2. Envelope tag with several declarations
<SOAP-ENV:Envelope
xmlns:SOAP-ENV
=
"http://schemas.xmlsoap.org/soap/envelope/"
SOAP-ENV:encodingStyle
=
"http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd
="http://www.w3.org/2001/XMLSchema"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance">
...rest of message
</SOAP-ENV:Envelope>
Besides specifying a namespace for the encoding rules, an envelope may define a default encoding style that should be assumed over all elements in the message that aren't explicitly assigned a different style. Later, other attributes will be discussed in the context of the header and body of the message. 5.2.3 The Header Tag: Routing and MoreThe Header tag is the only optional part of the basic SOAP message. Despite this, it is present more often than not. The header section of a message may include authentication credentials (as shown in Example 5-1), information about other servers the message will visit, transaction management, and so forth. Another way of looking at this is that headers provide metadata for the message, adding more detail and information.
Each tag that is a child element of header tag is
Example 5-1 showed a single block within the Header element, a block that provided authentication credentials for the caller. Example 5-3 uses the same Header but adds some additional blocks. Example 5-3. A header containing several blocks
<SOAP-ENV:Header>
<auth:Authorize xmlns:auth=
"http://auth.xmlsoap.org/auth/">
<type>user</type>
<name>soapclient</name>
<passwd>s0m3*th!ng</passwd>
</auth:Authorize>
<p:priority
xmlns:p="http://tasks.xmlsoap.org/priority"
SOAP-ENV:mustUnderstand="0">
<value xsi:type="xs:int"
>19</value>
</p:priority>
<tr:transaction xmlns:tr="soap-transaction
"
SOAP-ENV:mustUnderstand="1">
<transactionID>141421</transactionID>
</tr:transaction>
</SOAP-ENV:Header>
Taking the tags somewhat literally, it can be assumed that the second block acts to specify that the task may be run at a particular priority. It refers to a different namespace, and thus a completely separate specification from SOAP itself. Following the "priority" block is a third block that specifies a transaction identifier for the message. Its namespace is a relative URI computed against the namespace URI of the parent ( Header ) tag.
Both blocks also introduce a new piece of the SOAP picture. They each bear an attribute called
mustUnderstand
, that is qualified into the namespace that
SOAP-ENV
represents. The SOAP envelope provides two global attributes that may be used within blocks in the header:
mustUnderstand
and
actor
. In simple terms,
actor
5.2.3.1 The encodingStyle attribute
Looking back to Table 5-1, there are predefined namespaces for the basic encoding rules the SOAP specification provides. These are
Data encoding, and the differences in encoding styles themselves, are covered in greater detail later within this chapter. 5.2.3.2 Actors, roles, nodes, and responsibilityBefore looking at the actor (called a role in SOAP 1.2) and mustUnderstand settings, it may help to understand what actors and nodes are, in the context of a SOAP message.
A SOAP transaction isn't limited to just one receiver, or endpoint. The more traditional model of the client/server system has the server as the single destination of a message, with the response that the client receives coming completely from that server. In the SOAP model, a message may pass through several hands before reaching a final destination. Each intermediate step may act on and alter some part of the message before passing control to the
Each step on such a
SOAP
5.2.3.3 The actor/role attributesThere are two defined specific actors in SOAP 1.1, with a third one added to the specification with SOAP 1.2. The actor attribute is specified in the opening tag of a given block and must be qualified into the envelope namespace (as appropriate for the SOAP version). If there is no actor attribute in a block's tag, that block is said to be the responsibility of the anonymous actor . This actor represents the ultimate receiver of the message, regardless of the number of intermediate nodes involved.
The second of the common actor roles is the
current actor
. This refers to the currently active node. The
actor
attribute is set to a particular URI, slightly different between Versions 1.1 and 1.2, which
With SOAP 1.2, a third predefined role was added to the specification: that of the
null actor
. If a sender of a message wishes to
Table 5-2 lists these predefined actor roles and the URIs that identify them in SOAP 1.1 and 1.2: Table 5-2. The URIs that define actor roles
The third row is there to
5.2.3.4 The mustUnderstand attribute
The
mustUnderstand
attribute is used to tell the actor currently processing the message whether the block
The interpretation of the value is simple: when the value is true (either the explicit boolean
true
, or
1
), the block must be
When this attribute isn't present at all, it is the same as having it present with a value of (or false ). In Example 5-3, the authorization block doesn't have a mustUnderstand , so the default is used. Because of this, if the application doesn't understand the block, it's free to ignore it. 5.2.3.5 Attribute placement and exampleThe global attributes are recognized only when associated with the outer tag of a block; that is, the immediate children of the Header tag. Both versions of the specification allow for the attributes to be present in deeper tags but instruct that the application must ignore them in such cases. Because of this, all the blocks in Table 5-3 are equivalent. Table 5-3. Header blocks using mustUnderstand
With this ability, a client can, for example, specify a priority without the danger that a server might reject the request out-of-hand because of an inability to act on that part of the header. Example 5-4 shows a larger header with many content blocks to tie all this material together. The header shown here will be traced through several stages of processing by multiple nodes. Example 5-4. A complex header block, illustrating the attributes
<env:Header>
<t:data xmlns:t="null" env:actor=
"http://www.w3.org/2002/6/soap-envelope/role/none">
<value id="timestamp">1014457345</value>
</t:data>
<crm:userUpdate xmlns:crm="x-schema:crm_structure.xml"
env:mustUnderstand="true"
env:actor=
"http://www.w3.org/2002/6/soap-envelope/role/next">
<crm:userIdNum><value>501</value></crm:userIdNum>
</crm:userUpdate>
<cert:checkSignature xmlns:cert="http://cert.ssl.org/cert"
env:mustUnderstand="true"
env:actor="http://soap.ssl.org/soap/checkSignature">
<cert:signatureType>seeded-gpg</cert:signatureType>
<cert:signatureSeed>
<value href="#timestamp" />
</cert:signatureSeed>
<cert:pkKeySerial>128-4095-1014458368</cert:pkSerial>
<cert:md5>823dd310c0d0842b2b5e1b4d28822db9</cert:md5>
</cert:checkSignature>
<crm:enactUpdate xmlns:crm="x-schema:crm_structure.xml"
env:mustUnderstand="true"
env:actor="http://soap.blackperl.com/crm/enactUpdate">
<crm:userId>
<value href="#userID" />
</crm:userId>
<crm:updateTokens>
<value href="#data_in_body" />
</crm:updateTokens>
</crm:enactUpdate>
</env:Header>
This header contains four subblocks within it:
When the header is received, the node, filling the role of current actor, is responsible for the
userUpdate
block. For this example, assume that this node is expected to either verify that a valid user ID is present, or to retrieve one based on some information provided. Here, the numerical user ID is present as a
<value>
tag to
userUpdate
. This node must
<env:Header>
<t:data xmlns:t="null" env:actor=
"http://www.w3.org/2002/6/soap-envelope/role/none">
<value id="timestamp">1014457345</value>
</t:data>
<cert:checkSignature xmlns:cert="http://cert.ssl.org/cert"
env:mustUnderstand="true"
env:actor=
"
http://www.w3.org/2002/6/soap-envelope/role/next">
<cert:signatureType>seeded-gpg</cert:signatureType>
<cert:signatureSeed>
<value href="#timestamp" />
</cert:signatureSeed>
<cert:pkKeySerial>128-4095-1014458368</cert:pkSerial>
<cert:md5>823dd310c0d0842b2b5e1b4d28822db9</cert:md5>
</cert:checkSignature>
<crm:enactUpdate xmlns:crm="x-schema:crm_structure.xml"
env:mustUnderstand="true"
env:actor="http://soap.blackperl.com/crm/enactUpdate">
<crm:userId>
<value href="#userID" />
</crm:userId>
<crm:updateTokens>
<value href="#data_in_body" />
</crm:updateTokens>
</crm:enactUpdate>
<t:data xmlns:t="null" env:actor=
"
http://www.w3.org/2002/6/soap-envelope/role/none">
<value id="userID">rjray</value>
</t:data>
</env:Header>
The assumption here is that the process of checking the digital signature will immediately respond with an error notification (called a fault within SOAP, and discussed later in this chapter) back to the sender if the signature doesn't pass validation. Note that this block uses the data in the first header block, the one tagged with the null actor. Taking it on faith that the signature is valid, the key-service node creates a new message with the third-generation header as shown here:
<env:Header>
<data env:actor=
"http://www.w3.org/2002/6/soap-envelope/role/none">
<value id="timestamp">1014457345</value>
</data>
<crm:enactUpdate xmlns:crm="x-schema:crm_structure.xml"
env:mustUnderstand="true"
env:actor=
"
http://www.w3.org/2002/6/soap-envelope/role/next">
<crm:userId>
<value href="#userID" />
</crm:userId>
<crm:updateTokens>
<value href="#data_in_body" />
</crm:updateTokens>
</crm:enactUpdate>
<t:data xmlns:t="null" env:actor=
"http://www.w3.org/2001/12/soap-envelope/actor/none">
<value id="userID">rjray</value>
</t:data>
<cert:data xmlns:cert="http://cert.ssl.org/cert">
<cert:messageString>signature: good</cert:messageString>
<cert:messageCode>200</cert:messageCode>
</cert:data>
</env:Header>
With this final version of the header, it can be assumed that the node handling it is going to do the actual
Through this example, all the changes that were enacted by intermediaries took place within the header itself. In fact, the various nodes may add tag blocks to both the header or the body. 5.2.4 The Body Tag: Anatomy of a MessageThe chained examples just shown managed to illustrate a complex, multinode process that made little use of the message's body. According to the specification, the Body tag is still a required element. It also marks the end of the message because the Envelope tag is expected to close after the Body tag does.
As with the
Header
tag, the
Body
tag is required to be qualified with the same namespace as the
Envelope
tag. The opening tag of a message body doesn't provide any attributes itself. There is no purpose for any of the common SOAP attributes at this level. All child elements of the body may utilize the
encodingStyle
attribute. However,
Like the header of the message, the contents of the body must all bear namespace qualifiers. But unlike the header, the specification does provide one tag within the envelope's namespace that may appear within a body. This is the Fault tag, which is used in error reporting. Faults themselves are covered in detail later. The body isn't required to have any child elements. The only limitation on child elements is that only one Fault element can be present in a Body . So what role does the body of the message play? It carries information, just as the Header does (and to a lesser degree, the Envelope as well). The message body enjoys the distinction of always being present, and always being the responsibility of the ultimate recipient of the message. Intermediaries may add to the body of a message, but they are expected to not actually try to process any part of it in any way.
Depending on the nature of the application itself, the body of the message may be little more than a storehouse of information. In the extended set of header blocks that were traced in Examples Example 5-4 through Example 5-6, all the functionality of the request was contained in the headers of the message. Each of these tasks were directed by a header block: the look up of a username through numerical ID, the validation of the message against a digital signature, and the actual request to update the user information against whatever system was being
There are other ways this could have been done. For example, the digital signature application might have taken as part of its specification the element ID of one of the body's child elements. Applications on either side of the signature function could then have added their data to the body without interfering with the signature. The signature application itself didn't have to worry about changing the body because the signature was already computed and evaluated. All these choices were
Of course, the body can be responsible for much more than just carrying data. Encapsulation of RPC within SOAP can use the body to provide the remote call being marshaled, for example. The part of the header that provides the actual update can be placed within the body, instead of in the header. Bodies can contain many child elements, ranging from multiple application instructions to complex serialized objects. 5.2.5 Expressing and Encoding Data
Messages
Encoding (often called serialization ) of data within SOAP is considerably more complex than in XML-RPC. As such, trying to comprehend it just from the specification by itself can be an intimidating task. This is made even more complex by the fact that a message may use an encoding other than the basic SOAP encoding. In fact, a message may use several different encodings at various places within the envelope. Specifying these encodings is the role of the encodingStyle attribute described earlier. 5.2.5.1 XML Schema and encoding
The SOAP encoding model is based primarily on the XML Schema Language, generally referred to as XML Schema. This is
However, SOAP also requires that a message be manageable without forcing the recipient to process any schemas. Because of this, all attributes that are parts of data definitions must be present; they can't be assumed to be inherited from the corresponding schema. The encoding schema that describes the data serializations provided by SOAP is the one specified earlier in Table 5-1, in which the commonly used namespace labels were introduced. Refer to those URIs (for SOAP 1.1 and 1.2), as well as the URIs that are associated with the namespace labels xsi and xsd (the SOAP 1.2 specification uses xs in place of xsd ). While the URI is necessarily different for the basic SOAP encoding itself, both versions of SOAP use the same namespace URIs for the XML Schema declarations. 5.2.5.2 Simple types, values and enumerationsThrough XML Schema, SOAP provides some very familiar simple types, listed in Table 5-4. Table 5-4. Simple types available
Unlike XML-RPC, SOAP data is expressed in the form of named parameters . Take the following construct: <Name>James</Name>
This doesn't refer to
Name
as a type.
Name
is the parameter itself, and the string "James" is its value. It is
The XML Schema specification provides the definitions of these types, and attributes that may be used in qualifying elements that contain such data. However, no tags are provided by XML Schema directly. To aid in encoding values in places and situations in which the type may not be immediately known, the SOAP encoding schemas provide tags in their namespaces as a convenience. The previous fragment can also be written as follows: <Name><SOAP-ENC:string>James</SOAP-ENC:string></Name>
Within SOAP terminology (and
Likewise, one of the XML Schema types can also be provided in an attribute: <Lang xsi:type="xsd:string">Greek</Lang> This naming of data elements is what SOAP calls accessors. Accessors are explained in greater detail in a later section, but for now it is enough to understand that the name by which data is referred to is its accessor. When the type of the data a name refers to can be changed from one instance to the next using the type attribute, that is what SOAP considers polymorphic. To Perl, of course, it seems like an ordinary scalar.
One simple type remains, the
array of bytes
. This is a type provided as a "catch-all" of sorts, for data that doesn't conveniently fit into the other types, such as audio or image data. While the encoding isn't
<picture xsi:type="SOAP-ENC:base64"> aG93IG5vDyBicm73biBjb3cNCg== </picture> The general definition of the "base64" encoding includes limits on line length that aren't enforced in the context of SOAP values. Lines may be broken (or not broken) at any point convenient to the application. 5.2.5.3 Compound types and valuesSOAP and XML Schema provide for more complex data expression through compound types , types that are built up by creating associations of several other values under one name. Compound types come in two forms: the structure (sometimes referred to simply as struct ) and the array . The structure is a familiar concept. In terms of Perl, this may be thought of as similar to the hash table, in which the named values that make up the parts of the compound type are the key/value pairs, and the hash table itself represents the container. Any elements in a compound type may refer to a simple type or another compound type. Here's an example of a simple structure: <Book xmlns="http://www.loc.gov/schema"> <title>Perl Guidebook, The</title> <isbn>01-55677-1234</isbn> </Book> This corresponds to the simple hash:
%Book = (
title => 'Perl Guidebook, The',
isbn => '01-55677-1234'
);
As with the simple types, compound types are described using the XML Schema syntax. A schema fragment to describe the previous structure might look like this: <xs:element name="Book" type="tns:Book"/> <xs:complexType name="Book"> <xs:element name="title" type="xs:string"/> <xs:element name="isbn" type="xs:string"/> </xs:complexType> 5.2.5.4 Accessors, scoping, and reference
The introduction of the structure also means introducing the concept of the data
accessor
. The
An accessor in the SOAP sense of the word is the way a specific data element is uniquely referred to. In more traditional object-oriented terms, an accessor is generally a type of method that provides access to internal ("protected") class elements without exposing those elements directly. A SOAP accessor isn't a routine or method. In a structure, the name of the structure element is the accessor. This can mean that the accessor is a combined sequence of element names when referring to a deeply nested data element. In an array, the position within the array itself is the accessor. The scoping of an accessor is important when a specific accessor isn't unique throughout the entire message. For example, if a message body contains two or more instances of the same structure with the containing tags at the same depth within the Body content, an accessor can refer to either structure, unless there is enough information to narrow it down to one specific structure. But when the focus is already within a structure, an accessor to a piece of data contained within is valid, even though the same accessor points to a different value in a different structure. This is what is known as the scope of an accessor and isn't unlike the concept of scope within Perl. Another type of accessor is the reference . References in the XML sense aren't really new, either. Any opening tag may bear an id attribute whose value is a unique (within the message) string. Other tags may then refer to that element using the href attribute and providing the name as the value, as in Example 5.5. Example 5-5. Defining references between values<enc:string id="question-1"> What is the answer to life, the universe and everything? </enc:string> <enc:int id="answer-1">42</enc:int> <q:TestItem xmlns:q="http://testgiver.org/basic"> <q:Question href="#question-1"/> <q:Answer href="#answer-1"/> </q:TestItem>
Both versions of the SOAP specification strongly
<q:TestItem xmlns:q="http://testgiver.org/basic">
<q:Question>
What is the answer to life, the universerse and
everything?
</q:Question>
<q:Answer>42</q:Answer>
</q:TestItem>
Using references in such a simple fragment may not seem obvious, but references don't have to refer to the current document. A reference can point to an external resource, just as the
href
attribute often does within HTML. The
TestItem
tag may wish to refer to the answers externally, away from the
<q:TestItem xmlns:q="http://testgiver.org/basic"> <q:Question href="#question-1"/> <q:Answer href="http://test.server.edu/test-1#answer-1"/> </q:TestItem> Recall that the header blocks in Example 5-4 also used references, both to refer between the header and the body and to refer to data provided by intermediary processes. 5.2.5.5 Arrays and partial arraysAs was mentioned earlier, arrays are regarded as compound types in which the ordering of the elements provides the accessors, not the names, of the elements. Arrays may contain elements of any variety of types, including structures and other arrays. Arrays may also be constrained to a certain subset of types by proving type information in the opening tag or in the schema that defines the namespace being used. The arrayType attribute provided by the SOAP encoding namespace is the mechanism used to provide this information. The value of the arrayType attribute is a type identifier. That value is generally from the XML Schema namespace, but can also be other namespace-qualified types. Example 5-6 illustrates three arrays. Example 5-6. Different kinds of arrays
<enc:Array enc:arrayType="xs:int[3]">
<enc:int>1</enc:int>
<enc:int>2</enc:int>
<enc:int>3</enc:int>
</enc:Array>
<a:AnyThingGoes xmlns:a="something.xml"
enc:arrayType="xs:anyType[4]">
<enc:int>27</enc:int>
<enc:string>Three-cubed</enc:string>
<enc:float>3.14159</enc:float>
<enc:anyURI>http://www.oreilly.com</enc:anyURI>
</a:AnyThingGoes>
<loc:Booklist xsi:type="enc:Array"
xmlns:loc="http://www.loc.gov/schema"
enc:arrayType="loc:Book[2]">
<loc:Book>
<loc:title>Perl Guidebook, The</loc:title>
<loc:isbn>01-55677-1234</loc:isbn>
</loc:Book>
<loc:Book>
<loc:title>Perl Primer, The</loc:title>
<loc:isbn>01-55832-4321</loc:isbn>
</loc:Book>
</loc:Booklist>
The first of these is just an array of integers, while the second shows an array in which elements are different types. The third array uses the Book structure definition from an earlier fragment to define the element types. It also uses a tag taken from the same namespace to serialize the array itself.
In this example, the second array used a named parameter tag provided by a namespace that was defined in the opening tag. In the third example, the tag was again a named parameter, but the type was provided in an inline fashion, using the
xsi:type
attribute. The second array also
The
arrayType
attribute provides not only the type for the data, but the size of the array as well. The specifications define the format of the
arrayType
value using a set of rules similar to the style used for parser definitions. In simple terms, an array type definition has two parts: the element type and the dimension. The
dimension
is given in the last set of square brackets (
[
and
]
), and may be zero or more integers separated by commas. The
element type
may also be followed by a pair of brackets, which indicates that each array element is itself also an array. This inner set of brackets doesn't have any numbers in it, but has commas to show multiple dimension. It is the responsibility of the arrays in the data to provide their specific size information when they are serialized. Additionally, if the dimension of the array itself isn't given, that means the application should determine size by inspecting the data. Table 5-5 shows some declarations with their
Table 5-5. Sample arrayType values and explanations
The special type
You may have noticed that an array's size may be left to examination only in the case of single-dimensional arrays. A serialized array specifies elements only in a linear sequence. Thus, an array of dimension two or higher must explicitly provide the sizes of the dimensions. This is a change from C or Perl, in which secondary and later dimensions were implemented as arrays of references or pointers. In other words, the type int[5,5] isn't the same as int[5][5] . The latter isn't a valid type definition, for one thing, and the first declaration results in a series of 25 integer values being serialized, not 5 occurrences of a further 5-element array. The following 2x2 array shows this in more detail: <enc:Array enc:arrayType="xs:string[2,2]> <xs:string>Row 1, Column 1</xs:string> <xs:string>Row 1, Column 2</xs:string> <xs:string>Row 2, Column 1</xs:string> <xs:string>Row 2, Column 2</xs:string> </enc:Array> This may seem like an unusual approach, but it becomes more clear when encoding partial arrays and sparse arrays. Partial and sparse arrays are similar, but aren't identical. A partial array is one that isn't sent in its entirety. The elements that are sent are still considered to be ordered; they just don't represent a complete array, and they may not start at the very first element. The attribute offset provides the information as to where in the array the data starts. This fragment encodes elements 3 and 4 of a 5-element array: <enc:Array enc:arrayType="xs:int[5]" enc:offset="[2]"> <xs:int>3</xs:int> <xs:int>4</xs:int> </enc:Array>
In contrast, a
sparse
array is one in which some number of elements are sent, but there is no guarantee about the relative
<enc:Array enc:arrayType="xs:string[10,10]"> <xs:string enc:position="[2,4]">Row 3, Col 5</xs:string> <xs:string enc:position="[7,9]">Row 8, Col 10</xs:string> </enc:Array>
Using the position attribute, only two of the 100 elements are passed, but the receiver
References may also be used within arrays, including partial and sparse ones. The references may refer to individual data elements or to other arrays that are used to fill in when the datatype for the referencing array allows:
<enc:Array enc:arrayType="xs:int[ ][10]">
<enc:Array enc:arrayType="xs:int[10]">
<xs:int position="[9]">-1</xs:int>
<xs:int position="[0]">3</xs:int>
</enc:Array>
<enc:Array enc:position="[3]" href="#array-3"/>
</enc:Array>
The fragment defines a sparse array with 10 arrays of integers. The first slot (slot 0, since the opening tag had no offset , and the first child tag had no position attribute) has data for its slots 0 and 9. The fourth slot of the outer array is a reference elsewhere in the document, to what will presumably be an array whose type matches what is expected. 5.2.5.6 Structures and generic compound types
Returning
To further support generic compound data, the rules also allow for compound types that mix together accessors that are distinguished by type and accessors distinguished by ordinal position, as in Example 5-7. Example 5-7. A compound type with mixed accessors
<newUserList xmlns="http://linux.com/userSchema">
<ShellUser>
<name>rjray</name>
<shell>/bin/tcsh</shell>
<password xsi:type="md5pw">
8be3d7e3ccf03a98026acfce9dcc6487
</password>
</ShellUser>
<CvsUser>
<name>rjray</name>
<commitAccess xsi:type="xs:boolean">true</commitAccess>
<password xsi:type="md5pw">
8be3d7e3ccf03a98026acfce9dcc6487
</password>
</CvsUser>
<CvsUser>
<name>guest</name>
<commitAccess xsi:type="xs:boolean">false</commitAccess>
<password xsi:type="md5pw">
473640010efda30acaedea407ab4aa64
</password>
</CvsUser>
</newUserList>
5.2.5.7 The SOAP root attribute
When a serialization contains multiple values and structures that are all children of the
Body
tag, SOAP generally assumes that the first one is the root of the object graph. This isn't always the case,
All elements have an
The element that is considered the root may in some cases affect the way the message is deserialized for the server application. This is a very rarely used feature, and no examples were found in the specifications or
5.2.6 Signaling a Problem: FaultsThe last of the XML and serialization topics to be covered is the SOAP Fault . In the simplest terms, faults are errors. The Fault tag was referred to earlier when discussing the Body tag. It has the distinction of being the only preprovided child element for Body as defined by the SOAP specifications. If one of the SOAP nodes has a problem with the message, this is the mechanism for communicating the problem back to the original client.
In practice, a fault child element looks just like a structured datatype. The biggest difference is that the permitted
5.2.6.1 Fault elements
The elements within the
Fault
tag are
Table 5-6. The element tags of a fault
The SOAP 1.2 specification for faults also includes a fifth element, called Node . This identifies at which node the fault occurred, if the data is relevant. The updated specification also changes the content of the Code element, so that it uses child elements called Value and Subcode (the latter is optional). More information on SOAP 1.2 faults can be found in the specifications. The detail element can be an important piece of content. If the nature of the fault is a failure to process the message body, the detail element must be present, even if it contains no child tags. Likewise, the absence of this element can be safely interpreted as meaning that the fault was not related to the message body at all. No information on header-related errors may appear within detail . Any information on header-based errors must be provided in the header of the response. Each of the child elements present in a detail block may be namespace-qualified and may have their own encodingStyle attribute for more localized encoding.
5.2.6.2 Predefined faults
The designers of SOAP recognized that consistency in fault codes is an important aspect of interoperability between different
Both SOAP 1.1 and 1.2 define sets of fault codes to use as a basis for generating these diagnostics. Neither specification expects their list to be exhaustive or
Table 5-7
Table 5-7. The predefined faults for SOAP 1.1
Based on the model that SOAP 1.1 described, the previous codes would have appeared in forms more like VersionMismatch.SOAP1-1Required , or Client.MalformedBodyContent . The longer text of the error would be left to the faultstring field, with the other fields used where appropriate and required.
SOAP 1.2 provides a more complete fault model. Part of this is replacing the
Table 5-8. The predefined faults for SOAP 1.2
The two codes that are the exact same "name" as their SOAP 1.1 counterparts shouldn't be interpreted as exactly the same. The SOAP 1.2 definitions and restrictions are much more specific with regards to these predefined values. As was mentioned earlier, the SOAP 1.2 specification also goes into more depth on the exact contents of the remaining elements of a Fault block, depending on the error itself. Rather than reproduce all that here, when the specification is still in revision, you should check the sections of the SOAP 1.2 specification that deal with faults. One unfortunate reality of developing complex software is the need to provide clear, intuitive, and specific error messages. [3]
|