天天看點

SOAP協定介紹

SOAP是用在分散或分布的環境中交換資訊的簡單的協定,它是一個基于XML的協定,包括三個部分:封裝定義了一個描述消息中包含什麼内容以及如何處理它們的架構,編碼規則用于表示應用程式定義的資料類型的執行個體,另外還有一個表示遠端過程調用和應答的協定。SOAP被設計為可以與各種其它協定結合使用;但這篇文章僅描述如何将SOAP和HTTP及HTTP擴充架構相結合。 

1. 簡介

SOAP以XML形式提供了一個簡單、輕量的用于在分散或分布環境中交換結構化和類型資訊的機制。SOAP本身并沒有定義任何應用程式語義,如程式設計模型或特定語義的實作;實際上它通過提供一個有标準元件的包模型和在子產品中編碼資料的機制,定義了一個簡單的表示應用程式語義的機制。這使SOAP能夠被用于從消息傳遞到RPC的各種系統。

SOAP包括三個部分

  • SOAP封裝(見第4節)結構定義了一個整體架構用來表示消息中包含什麼内容,誰來處理這些内容以及這些内容是可選的或是必需的。
  • SOAP編碼規則(見第5節)定義了用以交換應用程式定義的資料類型的執行個體的一系列機制。
  • SOAP RPC表示(見第7節)定義了一個用來表示遠端過程調用和應答的協定。

雖然這三個部分都作為SOAP的一部分一起描述,但它們在功能上是相交的。特别的,封裝和編碼規則是在不同的名域中定義的,這種子產品性的定義方法增加了簡單性。在SOAP封裝,SOAP編碼規則和SOAPRPC協定之外,這個規範還定義了兩個協定的綁定,描述了在有或沒有HTTP擴充架構[6]的情況下,SOAP消息如何包含在HTTP消息[5]中被傳送。

1.1 設計目标

SOAP的主要設計目标是簡單性和可擴充性,這意味着傳統的消息系統和分布對象系統的某些性質不是SOAP規範的一部分。這些性質包括:

  • 分布式碎片收集
  • 成批傳送消息
  • 對象引用(要求分布式碎片收集)
  • 激活機制(要求對象引用)

1.2 符号約定

這篇文章中的關鍵字 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT","SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", 和"OPTIONAL"的解釋在RFC-2119 [2]中。 這篇文章中用到的名域字首 "SOAP-ENV" 和"SOAP-ENC"分别與"http://schemas.xmlsoap.org/soap/envelope/" 和"http://schemas.xmlsoap.org/soap/encoding/"關聯。整篇文檔中,名域字首“xsi”被假定為與URI"http://www.w3.org/1999/XMLSchema-instance“(在XMLSchema規範[11]定義)相連。類似的,名域字首”xsd“被假定為與URI"http://www.w3.org/1999/XMLSchema"(在[10]中定義)相連。名域字首”tns“用來表示任意名域。所有其它的名域字首都隻是例子。 

名域URI的基本形式”some-URI“表示某些依賴于應用程式或上下文的URI[4]。這個規範用擴充BNF(在RFC-2616[5] 描述)描述某些結構。

1.3 SOAP消息舉例

在這個例子中,GetLastTradePrice SOAP 請求被發往StockQuote服務。這個請求攜帶一個字元串參數和ticker符号,在SOAP應答中傳回一個浮點數。XML名域用來區分SOAP标志符和應用程式特定的标志符。這個例子說明了在第6節中定義的HTTP綁定。如果SOAP中管理XML負載的規則完全獨立于HTTP是沒有意義的,因為事實上該負載是由HTTP攜帶的。在Appendix A中有更多的例子。

例1 在HTTP請求中嵌入SOAP消息

POST /StockQuote HTTP/1.1 

Host: 

www.stockquoteserver.com 

Content-Type: text/xml; 

charset="utf-8" 

Content-Length: nnnn 

SOAPAction: 

"Some-URI" 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 

<SOAP-ENV:Body> 

<m:GetLastTradePrice xmlns:m="Some-URI"> 

<symbol>DIS</symbol> 

</m:GetLastTradePrice> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

下面是一條應答消息,包括HTTP消息,SOAP消息是其具體内容 :

例2 在HTTP應答中嵌入SOAP消息

HTTP/1.1 200 OK 

Content-Type: text/xml; 

charset="utf-8" 

Content-Length: 

nnnn 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 

<SOAP-ENV:Body> 

<m:GetLastTradePriceResponse xmlns:m="Some-URI"> 

<Price>34.5</Price> 

</m:GetLastTradePriceResponse> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

. SOAP消息交換模型

SOAP消息從發送方到接收方是單向傳送,但正如上面顯示的,SOAP消息經常以請求/應答的方式實作。SOAP實作可以通過開發特定網絡系統的特性來優化。例如,HTTP綁定(見第6節)使SOAP應答消息以HTTP應答的方式傳輸,并使用同一個連接配接傳回請求。不管SOAP被綁定到哪個協定,SOAP消息采用所謂的”消息路徑“發送,這使在終節點之外的中間節點可以處理消息。一個接收SOAP消息的SOAP應用程式必須按順序執行以下的動作來處理消息:識别應用程式想要的SOAP消息的所有部分 (見4.2.2節)檢驗應用程式是否支援第一步中識别的消息中所有必需部分并處理它。如果不支援,則丢棄消息(見4.4節)。在不影響處理結果的情況下,處理器可能忽略第一步中識别出的可選部分。如果這個SOAP應用程式不是這個消息的最終目的地,則在轉發消息之前删除第一步中識别出來的所有部分。為了正确處理一條消息或者消息的一部分,SOAP處理器需要了解:所用的交換方式(單向,請求/應答,多路發送等等),這種方式下接收者的任務,RPC機制(如果有的話)的使用(如第7節中所述),資料的表現方法或編碼,還有其它必需的語義。盡管屬性(比如SOAP encodingstyle,見4.1.1節)可以用于描述一個消息的某些方面,但這個規範并不 強制所有的接收方也必須有同樣的屬性并取同樣的屬性值。舉個例子,某一特定的應用可能知道一個元素表示一條遵循第7節約定的RPC請求,但是另外一些應用可能認為指向該元素的所有消息都用單向傳輸,而不是類似第7節的請求應答模式。 

(譯者注:互動雙方的SOAP消息并不一定要遵循同樣的格式設定,而隻需要以一種雙方可了解的格式交換資訊就可以了)

3. 與XML的關系

所有的SOAP消息都使用XML形式編碼(更多有關XML的資訊請見[7])一個SOAP應用程式産生的消息中,所有由SOAP定義的元素和屬性中必須包括正确的名域。SOAP應用程式必須能夠處理它接收到的消息中的SOAP名域(見4.4節),并且它可以處理沒有SOAP名域的SOAP消息,就象它們有正确的名域一樣。SOAP定義了兩個名域(更多有關XML名域的資訊請見[8])

  • SOAP封裝的名域标志符是"http://schemas.xmlsoap.org/soap/envelope/"
  • SOAP的編碼規則的名域标志符是"http://schemas.xmlsoap.org/soap/encoding/"

SOAP消息中不能包含文檔類型聲明,也不能包括消息處理指令。[7] SOAP使用"ID"類型"id"屬性來指定一個元素的唯一的标志符,同時該屬性是局部的和無需校驗的。SOAP使用"uri-reference"類型的"href"屬性指定對這個值的引用,同時該屬性是局部的和無需校驗的。這樣就遵從了XML規範[7],XMLSchema規範[11]和XML連接配接語言規範[9]的風格。除了SOAP mustUnderstand 屬性(見4.2.3節)和SOAPactor屬性(見4.2.2節)之外,一般允許屬性和它們的值出現在XML文檔執行個體或Schema中(兩者效果相同)。也就是說,在DTD或Schema中聲明一個預設值或固定值和在XML文檔執行個體中設定它的值在語義上相同。

4. SOAP封裝

SOAP消息是一個XML文檔,包括一個必需的SOAP封裝,一個可選的SOAP頭和一個必需的SOAP體。在這篇規範剩餘部分中,提到SOAP消息時就是指這個XML文檔。這一節中定義的元素和屬性的名域标志符為:

"http://schemas.xmlsoap.org/soap/envelope/" 。一個SOAP消息包括以下部分:1.在表示這個消息的XML文檔中,封裝是頂層元素。2.應用SOAP交換資訊的各方是分散的且沒有預先協定,SOAP頭提供了向SOAP消息中添加關于這條SOAP消息的某些要素(feature)的機制。SOAP定義了少量的屬性用來表明這項要素(feature)是否可選以及由誰來處理。(見4.2節)3.SOAP體是包含消息的最終接收者想要的資訊的容器(見4.3節)。SOAP為SOAP體定義了一個Fault元素用來報告錯誤資訊。文法規則如下所示:

封裝

  1. 元素名是 "Envelope"
  2. 在SOAP消息中必須出現。
  3. 可以包含名域聲明和附加屬性。如果包含附加屬性,這些屬性必須限定名域。類似的,"Envelope"可以包含附加子元素,這些也必須限定名域且跟在SOAP體元素之後。

SOAP頭 (見4.2節)

  1. 元素名是"Header"
  2. 在SOAP消息中可能出現。如果出現的話,必須是SOAP封裝元素的第一個直接子元素。
  3. SOAP頭可以包含多個條目,每個都是SOAP頭元素的直接子元素。所有SOAP頭的直接子元素都必須限定名域。

SOAP體 (見4.3節)

  1. 元素名是"Body"
  2. 在SOAP消息中必須出現且必須是SOAP封裝元素的直接子元素。它必須直接跟在SOAP頭元素(如果有)之後。否則它必須是SOAP封裝元素的第一個直接子元素。
  3. SOAP體可以包括多個條目,每個條目必須是SOAP體元素的直接子元素。SOAP體元素的直接子元素可以限定名域。SOAP定義了SOAPFault元素來表示錯誤資訊。

4.1.1 SOAP encodingStyle屬性

EncodingStyle全局屬性用來表示SOAP消息的序列化規則。這個屬性可以在任何元素中出現,作用範圍與名域聲明的作用範圍很相似,為這個元素的内容和它的所有沒有重載此屬性的子元素。SOAP消息沒有定義預設編碼。屬性值是一個或多個URI的順序清單,每個URI确定了一種或多種序列化規則,用來不同程度反序列化SOAP消息,舉例如下:

"http://schemas.xmlsoap.org/soap/encoding/" 

"http://my.host/encoding/restricted http://my.host/encoding/" 

""

第5節中定義的序列化規則由URI"http://schemas.xmlsoap.org/soap/encoding/" 确定。使用這個特定序列化規則的消息應該用encodingStyle屬性說明這一點。另外,所有以"http://schemas.xmlsoap.org/soap/encoding/"開頭的URI中的序列化規則與第5節中定義的SOAP編碼規則相一緻。一個零長度的URI("")明确顯示所含元素沒有任何編碼形式。這可以用來取消上一級元素的所有編碼聲明。

4.1.2 封裝版本模型

SOAP沒有定義正常的基于主版本号和輔版本号的版本形式。SOAP消息必須有一個封裝元素與名域"http://schemas.xmlsoap.org/soap/envelope/"關聯。如果SOAP應用程式接收到的SOAP消息中的SOAP封裝元素與其他的名域關聯,則視為版本錯誤,應用程式必須丢棄這個消息。如果消息是通過HTTP之類的請求/應答協定收到的,應用程式必須回答一個SOAP VersionMismatch 錯誤資訊(見4.4節)。

4.2 SOAP頭

SOAP為互相通信的團體之間提供了一種很靈活的機制:在無須預先協定的情況下,以分散但标準的方式擴充消息。可以在SOAP頭中添加條目實作這種擴充,典型的例子有認證,事務管理,支付等等。頭元素編碼為SOAP封裝元素的第一個直接子元素。頭元素的所有直接子元素稱作條目。條目的編碼規則如下:

一個條目有它的完整的元素名(包括名域URI和局部名)确定。SOAP頭的直接子元素必須有名域限制。

SOAP encodingStyle屬性可以用來訓示條目所用的編碼形式(見4.1.1節)

SOAP mustUnderstand屬性(見4.2.3節)和SOAPactor屬性(見4.2.2節)可以用來訓示如何處理這個條目以及由誰來處理。(見4.2.1節)

4.2.1 使用頭屬性

這一節中定義的SOAP頭屬性确定了SOAP消息的接收者應該怎樣按第2節中所述的方式處理消息。産生SOAP消息的SOAP應用程式,應該僅僅在SOAP頭元素的直接子元素中使用這些SOAP頭屬性。SOAP消息的接收者必須忽略所有不在SOAP頭元素的直接子元素中SOAP頭屬性。下面的例子是一個SOAP頭,包括一個元素标志符"Transaction","mustUnderstand"取值為"1"和數值5。這應該以如下方式編碼:

<SOAP-ENV:Header> 

<t:Transaction 

xmlns:t="some-URI" SOAP-ENV:mustUnderstand="1"> 

</t:Transaction> 

</SOAP-ENV:Header>

4.2.2 SOAP actor屬性

一個SOAP消息從始節點到終節點的過程中,可能沿着消息路徑經過一系列SOAP中間節點。一個SOAP中間節點是一個可以接收轉發SOAP消息的應用程式。中間節點和終節點由URI區分。可能SOAP消息的終節點并不需要所有部分,而在消息路徑上的一個和幾個中間節點可能需要這些内容。頭元素的接收者扮演的角色類似于一個過濾器,防止這些隻發給本接受者的消息部分擴散到其它節點。即一個頭元素的接收者必須不轉發這些頭元素到SOAP消息路徑上的下一個應用程式。同樣的,接收者可能插入一個相似的頭元素。SOAP actor全局屬性可以用于訓示頭元素的接收者。SOAP actor屬性的值是一個URI。

URI "http://schemas.xmlsoap.org/soap/actor/next"指出了第一個處理這個消息的SOAP應用程式需要這個頭元素。這類似于HTTP頭中用Connection域表示hop-by-hop範圍模型。省略SOAP actor屬性表示接收者是SOAP消息的終節點。如果這個屬性要生效,它必須出現在SOAP消息執行個體中。(見第3節和4.2.1節)

4.2.3 SOAP mustUnderstand屬性

SOAP mustUnderstand全局屬性用來訓示接受者在處理消息時這個條目是否必須處理。條目的接收者由SOAP actor屬性定義(見4.2.2節)。MustUnderstand屬性的值是"1" 或 "0"。缺少SOAP mustUnderstand屬性在語義上等同于它的值為"0"。如果一個頭元素的SOAP mustUnderstand屬性的值是"1",那麼條目的接受者必須或者遵守語義(如以元素的全名傳送)并按照語義正确的處理,或者放棄處理消息(見4.4節)。SOAP mustUnderstand 屬性考慮了消息演變的準确性(robust evolution)。必須假定包含SOAP mustUnderstand屬性且值為"1"的元素以某種方式修改了它們的父元素或同層元素的語義。以這種方式連接配接元素確定了語義上的變化不會被那些不能完全了解它的接收者忽略。如果這個屬性要生效,它必須出現在SOAP消息執行個體中。(見第3節和4.2.1節)

4.3 SOAP體

SOAP體元素提供了一個簡單的機制,使消息的最終接收者能交換必要的資訊。使用體元素的典型情況包括配置RPC請求和錯誤報告。體元素編碼為SOAP封裝元素的直接子元素。如果已經有一個頭元素,那麼體元素必須緊跟在頭元素之後,否則它必須是SOAP封裝元素的第一個直接子元素。體元素的所有直接子元素稱作體條目,每個體條目在SOAP體元素中編碼為一個獨立的元素。條目的編碼規則如下:

  • 一個條目由它的元素全名(包括名域URI和局部名)确定。SOAP體元素的直接子元素可能是名域限制的。
  • SOAP encodingStyle屬性可能用來訓示條目(見4.1.1節)的編碼方式。
  • SOAP定義了一個Fault條目用來報告錯誤資訊。(見4.4節)

4.3.1 SOAP頭和體的關系

雖然頭和體定義為獨立的元素,它們實際上是有關系的。體條目和頭條目的關系如下:體條目在語義上等同于actor屬性為預設值且mustUnderstand屬性值為"1"的頭條目。不使用actor屬性則表示預設的actor。(見4.2.2節)

4.4 SOAP錯誤

SOAP錯誤元素用于在SOAP消息中攜帶錯誤和(或)狀态資訊。如果有SOAP錯誤元素,它必須以以體條目的方式出現,并且在一個體元素中最多出現一次。SOAP錯誤元素定義了以下四個子元素:

  • faultcode

    faultcode元素給軟體提供了一個識别此錯誤的算法機制。SOAP錯誤元素必須有faultcode子元素,并且它的值必須是一個合法的名(在[8]節定義)。SOAP定義一些SOAP faultcode描述基本的SOAP錯誤(見4.4.1節)。

  • faultstring

    faultstring元素提供了一個錯誤解釋,而不是為了軟體處理。faultstring元素類似于HTTP中定義(見[5],第6.1節)的'Reason-Phrase'。SOAP錯誤元素必須有faultstring子元素,并且它應該提供一些錯誤本質的解釋資訊。

  • faultactor

    faultactor元素提供了在消息路徑上是誰導緻了錯誤發生的資訊(見第2節)。它類似于SOAP actor屬性(見4.2.2節),隻是SOAP actor指的是頭條目的目的地,faultactor指的是錯誤的來源。faultactor屬性的值是用來區分錯誤來源的URI。不是SOAP消息的最終目的地的應用程式必須在SOAP Fault元素中包含faultactor元素。消息的最終目的地可以使用faultactor元素明确的訓示是它産生了這個錯誤(參見下面的detail元素)

  • detail

    detail元素用來攜帶與Body元素有關的應用程式所要的錯誤資訊。如果Body元素的内容不能被成功的處理,則必須包含detail子元素。它不能用來攜帶屬于頭條目的錯誤資訊。頭條目的詳細出錯資訊必須由頭條目攜帶。Fault元素中沒有detail元素表示這個錯誤與Body元素的處理無關。在有錯誤的時候,這可以用來區分Body元素有沒有被正确的處理。detail元素的所有直接子元素稱作detail條目,并且每個detail條目在detail元素中編碼為獨立的元素。detail條目的編碼規則如下(參見例10): 一個detail條目由它的元素全名(包括名域URI和局部名)确定。SOAP體元素的直接子元素可能是名域限制的。SOAP encodingStyle屬性可能用來訓示detail條目(見4.1.1節)的編碼方式。也可以有其它的Fault子元素,隻要它們是名域限制的。

4.4.1 SOAP 錯誤代碼

在描述這個規範中定義的錯誤時,這一節中定義的Faultcode值必須用在faultcode元素中。這些faultcode值得名域标志符為"http://schemas.xmlsoap.org/soap/envelope/"。定義這個規範之外的方法時推薦(不要求)使用這個名域。預設的SOAP faultcode值以可擴充的方式定義,允許定義新的SOAP faultcode值,并與現有的faultcode值向後相容。使用的機制類似于HTTP中定義的1xx, 2xx,3xx等基本的狀态類(見[5]第10節),不過,它們定義為XML合法名(見 [8] 第3節 ),而不是整數。 字元"."(點)作為faultcode的分隔符,點左邊的錯誤代碼比右邊的錯誤代碼更為普通。如:

Client.Authentication

這篇文檔中定義的faultcode值是:

名稱 含義
VersionMismatch 處理方發現SOAP封裝元素有不合法的名域(見4.1.2節)
MustUnderstand 處理方不了解或者不服從一個包含值為"1"的
mustUnderstand 屬性的 SOAP頭元素的直接子元素。(見4.2.3節)

Client

Client錯誤類表示消息的格式錯誤或者不包含适當的正确資訊。例如,消息可能缺少正确的認證和支付資訊。一般地,它表示消息不能不作修改就重發。參見4.4節

SOAP Fault detail子元素的描述。

Server

Server錯誤類表示由于消息的處理過程而不是消息的内容本身使得消息消息不能正确的處理。例如,處理消息時可能要與其它處理器通信,但它沒有響應。這個消息可能在遲一點的時間處理成功。 SOAP Fault子元素的詳細資訊參見4.4節

5. SOAP編碼

SOAP編碼格式基于一個簡單的類型系統,概括了程式語言,資料庫和半結構化資料等類型系統的共同特性。一個類型或者是一個簡單的(标量的)類型,或者是由幾個部分組合而成的複合類型,其中每個部分都有自己的類型。以下将較長的描述這些類型。這一節定義了類型化對象的序列化規則。它分兩個層次。首先,給定一個與類型系統的符号系統一緻的Schema(譯者注:這裡的schema不是符合XML文法的schema,而僅僅表示廣義的用于表示消息結構的定義方式),就構造了XML文法的Schema。然後,給定一個類型系統的Schema和與這個Schema一緻的特定的值,就構造了一個XML文檔執行個體。反之,給定一個依照這些規則産生的XML文檔執行個體和初始的Schema,就可以構造初始值的一個副本。這一節中定義的元素和屬性的名域标志符為"http://schemas.xmlsoap.org/soap/encoding/"。下面的例子都假定在上一層的元素中聲明了名域。 

鼓勵使用這一節中描述的資料模型和編碼方式,但也可以在SOAP中使用其他的資料模型和編碼方式。(見4.1.1節)

5.1 XML中的編碼類型規則

XML允許非常靈活的資料編碼方式。SOAP定義了一個較小的規則集合。這一節在總的層次上定義了這些編碼規則,下一節将描述特定類型的編碼規則的細節。這一節定義的編碼規則可以與第7節中所述的RPC調用和應答映射結合使用。下面的術語用來描述編碼規則:

  • 一個"value"是一個字元串,類型(數字,日期,枚舉等等)的名或是幾個簡單值的組合。所有的值都有特定的類型。
  • 一個"simple value"沒有名部分, 如特定的字元串,整數,枚舉值等等。
  • 一個"compound value"是相關的值的結合,如定單,股票報表,街道位址等等。在"compound value"中,每個相關的值都潛在的以名,序數或這兩者來區分。這叫作"a ccessor"。複合值的例子有定單和股票報表等等。數組也是複合值。在複合值中,多個accessor有相同的名是允許的,例如RDF就是這樣做的。
  • 一個"array"是一個複合值,成員值按照在數組中的位置互相區分。
  • 一個"struct"也是一個複合值,成員值之間的唯一差別是accessor名,accessor名互不相同。
  • 一個"simple type"是簡單值的類,如叫做"string" "integer"的類,還有枚舉類等等。
  • 一個"compound type"是複合值的類。複合類型的例子有定單類,它們有相同的accessor名(shipTo, totalCost等),但可能會有不同的值(可能以後被設定為确定的值)。

在複合類型中,如果類型内的accessor名互不相同,但是可能與其他類型中的accessor名相同,即,accessor名加上類型名形成一個唯一的标志符,這個名叫作"局部範圍名"。如果名是直接或間接的基于URI的一部分,那麼不管它出現在什麼類型中,這個名本身就可以唯一标志這個accessor,這樣的名叫作"全局範圍名"。給定了schema中相關的值的序列化資訊,就可能确定某些值隻與某個accessor的一個執行個體有關。其它情況下則無法确定。當且僅當一個accessor引用一個值,這個值才能被視為"single-reference",如果有不止一個accessor引用它,那麼就将它視為"multi-reference"。注意,可能一個确定的值在一個schema中是"single-reference",而在另一個schema中是"multi-reference"。在語句構成上,一個元素可能是"independent" 或 "embedded"。一個獨立的元素指出現在序列化最頂層的任何元素。所有其它元素都是嵌入元素。雖然用xsi:type屬性可以使值的結構和類型變為自描述的,但是序列化規則允許值的類型僅僅參照schema而定。這樣的schema可能使用"XML Schema Part 1: Structures" [10]和"XML Schema Part 2: Datatypes" [11]中描述的符号系統,也可能使用其它符号系統。注意,雖然序列化規則可以用于除了數組和結構之外的複合類型,但是許多schema僅僅包含數組和結構類型。序列化規則如下:

所有的值以元素内容的形式表示。一個multi-reference值必須表示為一個獨立元素的内容,而一個single-reference值最好不要這樣表示(也可以這樣表示)。對于每個具有值的元素,值的類型時必須用下述三種方式之一描述:

  • 所屬元素執行個體有xsi:type屬性
  • 所屬元素是一個有SOAP-ENC:arrayType 屬性(該屬性可能是預設的)的元素的子元素,或者
  • 所屬元素的名具有特定的類型,類型可以由schema确定。

一個簡單值表示為字元資料,即沒有任何子元素。每個簡單值必須具有一個類型,這個類型或者是XML Schemas Specification, part 2 [11]有的類型,或者具有源類型(參見5.2節)。一個複合值編碼成一個元素的序列,每個accessor用一個嵌入元素表示,該元素的元素名和accessor的名一緻。如果accessor的名是局部于其所屬的類型的,則該元素的元素名不是合格的,否則對應的元素名是合格的。(參見5.4節) 

一個multi-reference的簡單值或複合值編碼成一個獨立的元素,這個元素包含一個局部的無需校驗的屬性,屬性名為"id",類型為"ID"(依照XML Specification [7])。值的每個accessor對應一個空元素,該元素有一個局部的,無需校驗的屬性,屬性名為"href",類型為" uri-reference "(依照XML Schema Specification [11]),"href"屬性的值引用了相對應的獨立元素的URI标志符。字元串和字元數組表示為multi-reference的簡單類型,但是特殊的規則使它們在普通的情況下能被更有效的表示(參見5.2.1節和5.2.3節)。字元串和字元數組值的accessor可能有一個名字為"id",類型為"ID"(依照XML Specification [7])的屬性。如果這樣,所有這個值的所有其它accessor編碼成一個空元素,這個元素有一個局部的,無需校驗的屬性,屬性名為"href",類型為" uri-reference "(依照XML Schema Specification [11]),"href"屬性的值引用了包含這個值的元素的URI标志符。編碼時允許一個值有多個引用,就像多個不同的值有多個引用一樣,但這僅在從上下文可以知道這個XML文檔執行個體的含義沒有改變時才可使用。數組是複合值(參見5.4.2節)。SOAP數組定義為具有類型"SOAP-ENC:Array"或從它衍生的類型.

SOAP數組可以時一維或多元,它們的成員以序數位置互相區分。一個數組值表示為反映這個數組的一系列元素,數組成員按升序出現。對多元數組來說,右邊的這一維變化最快。每個成員元素命名為一個獨立元素。(見規則2)SOAP數組可以是single-reference 或multi-reference值,是以可以表示為嵌入元素或獨立元素的内容。SOAP數組必須包含一個"SOAP-ENC:arrayType"屬性,它的值指定了包含元素的類型和數組的維數。"SOAP-ENC:arrayType"屬性的值定義如下:

arrayTypeValue = atype asize 

atype = QName *( rank ) 

rank = "[" *( "," ) "]" 

asize = "[" #length "]" 

length = 1*DIGIT

  • "atype"結構是被包含元素的類型名,它表示為QName并且作為類型限制在XML元素聲明的
  • "type"屬性中出現(這意味着被包含元素的所有值都要與該類型一緻,即在SOAP-ENC:a rrayType中引用的類型必須是每個數組成員的類型或超類型)。在arrays of arrays or "jagged arrays"的情況下,類型元件編碼為"innermost"類型且在從第一層開始的嵌套數組的每一層中,類型名後都跟随一個rank結構。多元數組編碼時從第一維起,每一維之間用逗号隔開。
  • "asize"結構包含一個以逗号分隔的清單,數值0,1或其它整數表示數組每一維的長度。整數0表示沒有指定詳細的大小,但是可能在檢查數組實際成員的大小後确定。例如,一個5個成員的整型數組的arrayTypeValue值為"int[][5]",它的atype值是int[]",asize值是"[5]"。同樣,一個3個成員的兩維整型數組的arrayTypeValue值為"int[,][3]",它的atype值是int[,]",asize值是"[3]"。

一個SOAP數組成員可能包含一個"SOAP-ENC:offset"屬性表示這一項在整個數組中的位置偏移值。這被用來訓示一個部分儲值數組(見5.4.2.1節)的位置偏移值。同樣,一個數組成員可能包含一個"SOAP-ENC:position"屬性表示這一項在整個數組中的位置,這被用來描述稀疏數組(見5.4.2.2節)的成員。"SOAP-ENC:offset" 和"SOAP-ENC:position"屬性值的定義如下:

arrayPoint = "[" #length "]"

偏移值和位置從0開始 

NULL值或預設值可能通過省略accssor元素來表示。NULL值也可能通過一個包含值為'1'的xsi:null屬性的accssor元素來表示,其它的依賴于應用程式的屬性和值也可能用來表示NULL值。注意,規則2允許獨立的元素和數組成員名不同于值類型的元素。

5.2 簡單類型

SOAP采用了"XML Schema Part 2: Datatypes"規範[11]"Built-in datatypes"節中的所有類型作為簡單類型,包括值和取值範圍。例如:

類型 舉例
int 58502
float 314159265358979E+1
negativeInteger -32768
string Louis "Satchmo" Armstrong

在XML Schema規範中聲明的資料類型可以直接用在元素schema中,也可以使用從這些類型衍生的新類型。一個schema和對應的具有這些類型的元素的資料執行個體的例子如下所示:

<element name="age" type="int"/> 

<element name="height" type="float"/> 

<element name="displacement" type="negativeInteger"/> 

<element name="color"> 

<simpleType base="xsd:string"> 

<enumeration value="Green"/> 

<enumeration value="Blue"/> 

</simpleType> 

</element> 

<age>45</age> 

<height>5.9</height> 

<displacement>-450</displacement> 

<color>Blue</color>

所有簡單值必須編碼為元素的内容,它的類型或者在"XML Schema Part 2: Datatypes"規範[11]中定義過,或者是基于一個用XML Schema規範提供的機制能推衍生出的類型。如果一個簡單值編碼為獨立元素或異質數組成員,那麼有一個對應于資料類型的元素聲明将會很友善。因為"XML Schema Part 2: Datatypes"規範[11]包括了類型定義,但是不包括對應的元素聲明,SOAP-ENC schema和名域為每個簡單資料類型聲明了一個元素,如<SOAP-ENC:int id="int1">45</SOAP-ENC:int>

5.2.1 字元串

字元串資料類型的定義在"XML Schema Part 2: Datatypes"規範[11]中。注意,這不同于許多資料庫和程式語言中的"string"類型,特别的,字元串資料類型可能禁止某些在那些語言中允許的字元。(這些值必須用xsd:string之外的資料類型表示)一個字元串可能編碼為一個single-reference 或 multi-reference值。包含字元串值的元素可能有一個"id"屬性。附加的accessor元素可能有對應的"href"屬性。 

例如,同一字元串的兩個accessor可能以如下形式出現:

<greeting id="String-0">Hello</greeting> 

<salutation href="#String-0" target="_blank" rel="external nofollow" />

但是,如果兩個accessor參考同一字元串執行個體(或字元串的子類型),這不是一個實質問題,它們可以編碼為兩個single-reference值,如下所示:

<greeting>Hello</greeting> 

<salutation>Hello</salutation>

這個例子的schema片斷如下所示:

<element name="greeting" type="SOAP-ENC:string"/> 

<element name="salutation" type="SOAP-ENC:string"/>

在這個例子中,SOAP-ENC:string類型用作元素的類型,這是聲明資料類型是"xsd:string"且允許"id" 和"href"屬性的元素的簡便方法。精确定義參見SOAP編碼schema。Schemas可以使用這些源自SOAP編碼schema的聲明,但也可以不這樣做。

5.2.2 Enumerations

"XML Schema Part 2: Datatypes"規範 [11] 定義了"enumeration."機制。SOAP資料模型直接采用了這種機制。但是,由于程式語言和其它語言在定義枚舉時通常有些不同,是以我們在這裡詳細闡述了它的概念并描述了一個清單成員的可能取的值是如何編碼的。"Enumeration"作為一個概念表示不同的名字的集合。一個特定的枚舉就是對應于特定的基類型的不同的值的清單。例如,顔色集合("Green", "Blue", "Brown")可以定義為基于字元串類型的枚舉,("1", "3", "5")可能是一個基于整型數的枚舉,等等。"XML Schema Part 2: Datatypes" [11]支援除了布爾型以外所有簡單類型的枚舉。"XML Schema Part 1: Structures"規範[10]的語言可以用來定義枚舉類型。如果schema由另一個沒有特定基類型适用的符号系統生成,就使用"string"。在下面schema的例子中,"EyeColor"定義為字元串,可能的值是"Green", "Blue", 或"Brown"的枚舉,資料執行個體按照schema顯示如下。

<element name="EyeColor" type="tns:EyeColor"/> 

<simpleType name="EyeColor" base="xsd:string"> 

<enumeration value="Green"/> 

<enumeration value="Blue"/> 

<enumeration value="Brown"/> 

</simpleType> 

<Person> 

<Name>Henry Ford</Name> 

<Age>32</Age> 

<EyeColor>Brown</EyeColor> 

</Person>

5.2.3 字元數組

一個字元數組可能編碼為single-reference 或multi-reference值。字元數組的編碼規則與字元串的編碼規則類似。特别的,包含字元數組的元素值可能由一個"id"屬性,附加的accssor元素可能有相應的"href"屬性。推薦使用定義在XML Schemas [10][11]中的'base64'編碼(使用在2045 [13]中定義的base64編碼算法)表示模糊字元數組。不過,由于行長度(line length)的限制,通常在MIME中應用base64編碼,SOAP中一般不應用base64編碼。但是提供了"SOAP-ENC:base64"子類型使之能用于SOAP。

<picture xsi:type="SOAP-ENC:base64"> 

aG93IG5vDyBicm73biBjb3cNCg== 

</picture>

5.3 多态accessor

許多語言允許能夠多态通路多種類型值的accessor,每種類型在運作時可用。一個多态accessor執行個體必須包含一個"xsi:type"屬性描述實際值的類型。例如,一個名為"cost"類型值為"xsd:float"的多态accessor編碼如下:

<cost xsi:type="xsd:float">29.95</cost>與之對比,類型值不變的accessor編碼如下:

<cost>29.95</cost>

5.4 Compound types複合類型

SOAP定義了與下列常在程式語言中出現的結構性模式對應的類型:

  • 結構:一個"struct"是一個複合值,它的成員值的唯一差別是accessor名稱,任意兩個accessor名稱都不相同。
  • 數組:一個"array"是一個複合值,它的成員值的唯一差別是序數位置。

SOAP也允許結構和數組之外的其它資料的序列化,例如Directed-Labeled-Graph Data Model之類的資料中,單個節點有許多不同的accssor,有些不止出現一次。SOAP序列化規則不要求底層的資料模型在accssor之間區分次序,但如果有這樣的次序的話,這些accssor必須按照這個順序編碼。

5.4.1 複合值,結構和值引用

複合值的成員編碼為accessor元素。當accessor由名區分時(如結構),accessor名即作為元素名。名局部于類型的accessor有不受限的名,其它的accessor則有受限的名。下面的例子是類型為"Book"的結構:

<e:Book> 

<author>Henry Ford</author> 

<preface>Prefatory text</preface> 

<intro>This is a book.</intro> 

</e:Book>

以下是描述上面結構的schema片斷:

<element name="Book"> 

<complexType> 

<element name="author" type="xsd:string"/> 

<element name="preface" type="xsd:string"/> 

<element name="intro" type="xsd:string"/> 

</complexType> 

</e:Book>

以下是一個同時具有簡單和複雜成員類型的例子。它顯示兩層引用。注意"Author"accssor元素的"href"屬性是對相應具有"id"屬性的值的引用。"Address"與之類似。

<e:Book> 

<title>My Life and Work</title> 

<author href="#Person-1" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" /> 

</e:Book> 

<e:Person id="Person-1"> 

<name>Henry Ford</name> 

<address href="#Address-2" target="_blank" rel="external nofollow" /> 

</e:Person> 

<e:Address id="Address-2"> 

<email>mailto:[email protected]</email> 

<web>http://www.henryford.com</web> 

</e:Address>

當"Person"的值和"Address"的值是multi-reference時,上面的形式是正确的。如果它 

們是single-reference,就必須用嵌入的形式,如下所示:

<e:Book> 

<title>My Life and Work</title> 

<author> 

<name>Henry Ford</name> 

<address> 

<email>mailto:[email protected]</email> 

<web>http://www.henryford.com</web> 

</address> 

</author> 

</e:Book>

如果添加一個限制,任意兩個人都不會有相同的位址,并且位址可以是街道或Email位址,一本書可以有兩個作者,編碼如下:

<e:Book> 

<title>My Life and Work</title> 

<firstauthor href="#Person-1" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" /> 

<secondauthor href="#Person-2" target="_blank" rel="external nofollow" /> 

</e:Book> 

<e:Person id="Person-1"> 

<name>Henry Ford</name> 

<address xsi:type="m:Electronic-address"> 

<email>mailto:[email protected]</email> 

<web>http://www.henryford.com</web> 

</address> 

</e:Person> 

<e:Person id="Person-2"> 

<name>Samuel Crowther</name> 

<address xsi:type="n:Street-address"> 

<street>Martin Luther King Rd</street> 

<city>Raleigh</city> 

<state>North Carolina</state> 

</address> 

</e:Person>

序列化可以包含對不在同一個資源的值的引用:

<e:Book> 

<title>Paradise Lost</title> 

<firstauthor href="http://www.dartmouth.edu/~milton/" target="_blank" rel="external nofollow" /> 

</e:Book>

以下是描述上面結構的schema片斷:

<element name="Book" type="tns:Book"/> 

<complexType name="Book"> 

<!-- Either the following group must occur or else the 

href attribute must appear, but not both. --> 

<sequence minOccurs="0" maxOccurs="1"> 

<element name="title" type="xsd:string"/> 

<element name="firstauthor" type="tns:Person"/> 

<element name="secondauthor" type="tns:Person"/> 

</sequence> 

<attribute name="href" type="uriReference"/> 

<attribute name="id" type="ID"/> 

<anyAttribute namespace="##other"/> 

</complexType> 

<element name="Person" base="tns:Person"/> 

<complexType name="Person"> 

<!-- Either the following group must occur or else the 

href attribute must appear, but not both. --> 

<sequence minOccurs="0" maxOccurs="1"> 

<element name="name" type="xsd:string"/> 

<element name="address" type="tns:Address"/> 

</sequence> 

<attribute name="href" type="uriReference"/> 

<attribute name="id" type="ID"/> 

<anyAttribute namespace="##other"/> 

</complexType> 

<element name="Address" base="tns:Address"/> 

<complexType name="Address"> 

<!-- Either the following group must occur or else the 

href attribute must appear, but not both. --> 

<sequence minOccurs="0" maxOccurs="1"> 

<element name="street" type="xsd:string"/> 

<element name="city" type="xsd:string"/> 

<element name="state" type="xsd:string"/> 

</sequence> 

<attribute name="href" type="uriReference"/> 

<attribute name="id" type="ID"/> 

<anyAttribute namespace="##other"/> 

</complexType>

5.4.2 數組

SOAP數組定義為具有"SOAP-ENC:Array"類型或一個從"SOAP-ENC:Array"衍生的類型(參見規則8)。數組表示為元素值,對元素的名沒有特别的限制(正如元素值并不限制它們所屬的元素)。數組可以包含任意類型的元素,包括嵌套數組。可以建立新的類型(受SOAP-ENC:Array 

類型限制)來表示數組,如整數數組或某些使用者定義的枚舉。數組值表示為組成這個數組的項的元素的規則序列。在數組值中,元素名對于區分accesor并不重要。元素可以有任意的名。實際上,元素常常用它們在schema中暗示或确定的數組類型來命名元素。并且一般情況下對于複合值來說,如果數組中數組項的值是single-reference值,則這個數組項包含它的值,否則,該數組項通過"href"屬性引用這個值。下面的例子是一個整型數組的schema片斷:

<element name="myFavoriteNumbers" 

type="SOAP-ENC:Array"/> 

<myFavoriteNumbers 

SOAP-ENC:arrayType="xsd:int[2]"> 

<number>3</number> 

<number>4</number> 

</myFavoriteNumbers>

在這個例子中,數組"myFavoriteNumbers"包括幾個成員,每個成員是一個類型為SOAP-ENC:int的值。注意SOAP-ENC:Array允許不受限制的元素名,它們不傳達任何類型資訊,是以在使用時,或者它們有xsi:type屬性,或者它們所屬的元素有SOAP-ENC:arrayType屬性。自然,由SOAP-ENC:Array衍生的類型可以聲明局部元素,但這種情況下要包括類型資訊。上面已經提到,SOAP-ENC schema包含了元素的聲明,元素名與"XML Schema Part 2: Datatypes"規範[11]中的簡單類型一緻。其中包括了對"Array"的聲明。于是,我們可以這樣寫:

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:int[2]"> 

<SOAP-ENC:int>3</SOAP-ENC:int> 

<SOAP-ENC:int>4</SOAP-ENC:int> 

</SOAP-ENC:Array>

數組可以包含特定arrayType的任意子類型的執行個體。即,數組成員可以是arryType屬性值指定的類型的任意子類型,這個類型對于arrayType屬性中指定的類型來說是可替換的(根據schema中的替換規則)。例如,一個整型數組可以包含從整型衍生的任意類型(如"int"或任意使用者定義的從整型衍生的類型)。同樣,一個"address"數組可能包含一個address的受限類型或擴充類型如"internationalAddress"。因為提供的SOAP-ENC:Array類型允許任意類型的成員,是以可以包含任意類型的混合除非使用arrayType屬性加以特别的限制。在執行個體中,可以使用xsi:type指定成員元素的類型,或通過schema中成員元素的聲明來指定。下面是兩個例子。

<SOAP-ENC:Array SOAP-ENC:arrayType="SOAP-ENC:ur-type[4]"> 

<thing xsi:type="xsd:int">12345</thing> 

<thing xsi:type="xsd:decimal">6.789</thing> 

<thing xsi:type="xsd:string"> 

Of Mans First Disobedience, and the Fruit 

Of that Forbidden Tree, whose mortal tast 

Brought Death into the World, and all our woe, 

</thing> 

<thing xsi:type="xsd:uriReference"> http://www.dartmouth.edu/~milton/reading_room/ </thing> 

</SOAP-ENC:Array> 

<SOAP-ENC:Array SOAP-ENC:arrayType="SOAP-ENC:ur-type[4]"> 

<SOAP-ENC:int>12345</SOAP-ENC:int> 

<SOAP-ENC:decimal>6.789</SOAP-ENC:decimal> 

<xsd:string> 

Of Mans First Disobedience, and the Fruit 

Of that Forbidden Tree, whose mortal tast 

Brought Death into the World, and all our woe, 

</xsd:string> 

<SOAP-ENC:uriReference> http://www.dartmouth.edu/~milton/reading_room/ </SOAP-ENC:uriReference > 

</SOAP-ENC:Array>

數組值可以是結構或其它複合值。例如"xyz:Order"結構數組:

<SOAP-ENC:Array SOAP-ENC:arrayType="xyz:Order[2]"> 

<Order> 

<Product>Apple</Product> 

<Price>1.56</Price> 

</Order> 

<Order> 

<Product>Peach</Product> 

<Price>1.48</Price> 

</Order> 

</SOAP-ENC:Array>

數組成員值也可以是數組。下例是兩個字元串數組組成的數組:

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[][2]"> 

<item href="#array-1" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" /> 

<item href="#array-2" target="_blank" rel="external nofollow" /> 

</SOAP-ENC:Array> 

<SOAP-ENC:Array id="array-1" SOAP-ENC:arrayType="xsd:string[2]"> 

<item>r1c1</item> 

<item>r1c2</item> 

<item>r1c3</item> 

</SOAP-ENC:Array> 

<SOAP-ENC:Array id="array-2" SOAP-ENC:arrayType="xsd:string[2]"> 

<item>r2c1</item> 

<item>r2c2</item> 

</SOAP-ENC:Array>

包含數組的元素無需命名為"SOAP-ENC:Array"。它可以有任意的名,隻要元素的類型是SOAP-ENC:Array或由之衍生的類型。例如,下面是一個schema片斷和與之一緻的數組執行個體。

<simpleType name="phoneNumber" base="string"/> 

<element name="ArrayOfPhoneNumbers"> 

<complexType base="SOAP-ENC:Array"> 

<element name="phoneNumber" type="tns:phoneNumber" maxOccurs="unbounded" /> 

</complexType> 

<anyAttribute/> 

</element> 

<xyz:ArrayOfPhoneNumbers SOAP-ENC:arrayType="xyz:phoneNumber[2]"> 

<phoneNumber>206-555-1212</phoneNumber> 

<phoneNumber>1-888-123-4567</phoneNumber> 

</xyz:ArrayOfPhoneNumbers>

數組可能是多元的。在這種情況下,在arrayType屬性的asize部分将不止有一個值:

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[2,3]"> 

<item>r1c1</item> 

<item>r1c2</item> 

<item>r1c3</item> 

<item>r2c1</item> 

<item>r2c2</item> 

<item>r2c3</item> 

</SOAP-ENC:Array>

雖然上面的例子把數組編碼為獨立的元素,但元素值也可以是嵌入形式,而且若元素值是single reference時,必須編碼為嵌入形式。下例是一個schema片斷,電話号碼數組嵌入到一個類型為"Person"的結構中,并且通過accessor "phone-numbers"通路它:

<simpleType name="phoneNumber" base="string"/> 

<element name="ArrayOfPhoneNumbers"> 

<complexType base="SOAP-ENC:Array"> 

<element name="phoneNumber" type="tns:phoneNumber" maxOccurs="unbounded"/> 

</complexType> 

<anyAttribute/> 

</element> 

<element name="Person"> 

<complexType> 

<element name="name" type="string"/> 

<element name="phoneNumbers" type="tns:ArrayOfPhoneNumbers"/> 

</complexType> 

</element> 

<xyz:Person> 

<name>John Hancock</name> 

<phoneNumbers SOAP-ENC:arrayType="xyz:phoneNumber[2]"> 

<phoneNumber>206-555-1212</phoneNumber> 

<phoneNumber>1-888-123-4567</phoneNumber> 

</phoneNumbers> 

</xyz:Person>

下面的例子中,數組值為single-reference,被編碼為嵌入元素,包含它的元素名即為入口名:

<xyz:PurchaseOrder> 

<CustomerName>Henry Ford</CustomerName> 

<ShipTo> 

<Street>5th Ave</Street> 

<City>New York</City> 

<State>NY</State> 

<Zip>10010</Zip> 

</ShipTo> 

<PurchaseLineItems SOAP-ENC:arrayType="Order[2]"> 

<Order> 

<Product>Apple</Product> 

<Price>1.56</Price> 

</Order> 

<Order> 

<Product>Peach</Product> 

<Price>1.48</Price> 

</Order> 

</PurchaseLineItems> 

</xyz:PurchaseOrder>

5.4.2.1 部分儲值(partially transmitted)數組

SOAP提供了對部分儲值(partially transmitted)數組的支援,如某些上下文中的可變數組。一個partially transmitted 數組由一個"SOAP-ENC:offset"屬性(從第一個transmitted的元素開始的偏移量,基于0)訓示。如果省略,偏移量取0。下面的例子中數組的大小為5,但隻有從0起,第三和第四個元素被儲值。

<SOAP-ENC:Array ;SOAP-ENC:arrayType="xsd:string[5]" ;SOAP-ENC:offset="[2]"> 

<item>The third element</item> 

<item>The fourth element</item> 

</SOAP-ENC:Array>

5.4.2.2 稀疏數組Sparse Arrays

SOAP提供了對稀疏數組的支援。每個表示成員值的元素包含一個"SOAP-ENC:position"屬性,用來訓示它在數組中的位置。下例是兩維字元串稀疏數組的例子,數組大小是4,但隻用到第2個。

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[,][4]"> 

<SOAP-ENC:Array href="#array-1" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" SOAP-ENC:position="[2]"/> 

</SOAP-ENC:Array> 

<SOAP-ENC:Array id="array-1" SOAP-ENC:arrayType="xsd:string[10,10]"> 

<item SOAP-ENC:position="[2,2]">Third row, third col</item> 

<item SOAP-ENC:position="[7,2]">Eighth row, third col</item> 

</SOAP-ENC:Array>

如果對array-1的引用僅發生在數組内部,上例也可以編碼如下:

<SOAP-ENC:Array SOAP-ENC:arrayType="xsd:string[,][4]"> 

<SOAP-ENC:Array SOAP-ENC:position="[2]" SOAP-ENC:arrayType="xsd:string[10, 10]> 

<item SOAP-ENC:position="[2,2]">Third row, third col</item> 

<item SOAP-ENC:position="[7,2]">Eighth row, third col</item> 

</SOAP-ENC:Array> 

</SOAP-ENC:Array>

5.4.3 一般複合類型

在這裡提到的編碼規則不僅僅限于accessor名已知的情況,如果accessor名是運作環境下實時獲得的,編碼規則同樣适用,也就是說accessor編碼成一個元素名與accessor名比對的元素,同時accessor可能包含或者引用該元素的值。如果accessor包含類型不能事先确定的值,它必須包含一個合适的屬性xsi:type 。類似地,上述引用的規則已經足夠用于複合類型的序列化,這些複合類型可能包含用名區分的accessors(結構)和用名及序數位置區分的accessors。(可能包含重複的accessor) 實際上這并不要求任何schema模式包含這些類型,但更為準确的說法是:一個類型模型(type-model)schema如果有這些類型,就可以構造一個符合XML句法規則的schema和XML文檔執行個體。

<xyz:PurchaseOrder> 

<CustomerName>Henry Ford</CustomerName> 

<ShipTo> 

<Street>5th Ave</Street> 

<City>New York</City> 

<State>NY</State> 

<Zip>10010</Zip> 

</ShipTo> 

<PurchaseLineItems> 

<Order> 

<Product>Apple</Product> 

<Price>1.56</Price> 

</Order> 

<Order> 

<Product>Peach</Product> 

<Price>1.48</Price> 

</Order> 

</PurchaseLineItems> 

</xyz:PurchaseOrder>

類似地,将一個結構上類似數組但實際上不是一個 SOAP-ENC:Array類型或者 SOAP-ENC:Array子類型的複合值序列化同樣是允許的,例如:

<PurchaseLineItems> 

<Order> 

<Product>Apple</Product> 

<Price>1.56</Price> 

</Order> 

<Order> 

<Product>Peach</Product> 

<Price>1.48</Price> 

</Order> 

</PurchaseLineItems>

5.5 預設值

省略accessor元素意味着或者有一個預設值或者值不知道。具體細節依靠這個accessor,方法和上下文。例如,對于多态accessor,省略accessor一般意味着一個Null值。同樣,省略布爾accessor一般意味着False值或者值不知道,省略數字accessor一般意味着值為零或者值不知道。

5.6 SOAP root屬性

SOAP root 屬性可用于标記一個序列化root,進而一個對象可以反序列化(deserialized),而實際上該root并不是真正的對象root。這個屬性有兩個可選值"1" or "0"。對象真正的roots屬性值為“1” ,序列化root但不是真正的root屬性值也為“1”,元素如果要顯式地指定不能為序列化root,隻需将該屬性設定為“0” SOAP root屬性可以出現在SOAP頭和SOAP體元素的任意子元素中。(譯者注:SOAP root屬性為0的元素不是一個獨立的實體,外部的應用不能通路到該元素,但該元素可以被SOAP文檔本身的其它元素通路到)SOAP root屬性可以出現在SOAP頭和SOAP體元素的任意子元素中。這個屬性沒有預設值。

6. 在HTTP中使用SOAP

這一節講述了如何在HTTP中使用SOAP。把SOAP綁定到HTTP,無論使用或不用HTTP擴充架構,都有很大的好處:在利用SOAP的形式化和靈活性的同時,使用HTTP種種豐富的特性。在HTTP中攜帶SOAP消息,并不意味着SOAP改寫了HTTP已有的語義,而是将建構在HTTP之上SOAP語義自然地對應到HTTP語義。SOAP自然地遵循HTTP的請求/應答消息模型使得SOAP的請求和應答參數可以包含在HTTP請求和應答中。注意,SOAP的中間節點與HTTP的中間節點并不等同,即,不要期望一個根據HTTP連接配接頭中的域尋址到的HTTP中間節點能夠檢查或處理HTTP請求中的SOAP消息。 

在HTTP消息中包含SOAP實體時,按照RFC2376[3] HTTP應用程式必須使用媒體類型 "text/xml"。

6.1 SOAP HTTP請求

雖然SOAP可能與各種HTTP請求方式相結合,但是綁定僅定義了在HTTP POST請求中包含SOAP消息。(第7節中描述了如何在RPC中使用SOAP,第6.3節描述了如何使用HTTP擴充架構)

6.1.1 HTTP頭中SOAPAction域

一個HTTP請求頭中的SOAPAction域用來指出這是一個SOAP HTTP請求,它的值是所要的URI。在格式、URI的特性和可解析性上沒有任何限制。當HTTP客戶發出SOAP HTTP請求時必須使用在HTTP頭中使用這個域。

soapaction = "SOAPAction" ":" [ <"> URI-reference <"> ] 

URI-reference = <as defined in RFC 2396 [4]>

HTTP頭中SOAPAction域使伺服器(如防火牆)能正确的過濾HTTP中SOAP請求消息。如果這個域的值是空字元串(""),表示SOAP消息的目标就是HTTP請求的URI。這個域沒有值表示沒有SOAP消息的目标的資訊。例子:

SOAPAction: "http://electrocommerce.org/abc#MyMessage" 

SOAPAction: "myapp.sdl" 

SOAPAction: "" 

SOAPAction:

6.2 SOAP HTTP應答

SOAP HTTP遵循HTTP 中表示通信狀态資訊的HTTP狀态碼的語義。例如,2xx狀态碼表示這個包含了SOAP元件的客戶請求已經被成功的收到,了解和接受。在處理請求時如果發生錯誤,SOAP HTTP伺服器必須發出應答HTTP 500 "Internal Server Error",并在這個應答中包含一個SOAP Fault元素(見4.4節)表示這個SOAP處理錯誤。

6.3 HTTP擴充架構

一個SOAP消息可以與HTTP擴充架構 [6]一起使用以區分是否有SOAP HTTP請求和它的目标。是使用擴充架構或是普通的HTTP關系到通信各方的政策和能力。通過使用一個必需的擴充聲明和"M-"HTTP方法名字首,客戶可以強制使用HTTP擴充架構。伺服器可以使用HTTP狀态碼510 "Not Extended"強制使用HTTP擴充架構。也就是說,使用一個額外的來回,任何一方都可以發現另一方的政策并依照執行。用來表示SOAP使用了擴充架構的擴充标志符是:http://schemas.xmlsoap.org/soap/envelope/

6.4 SOAP HTTP舉例

例3 使用POST的SOAP HTTP

POST /StockQuote HTTP/1.1 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

SOAPAction: "http://electrocommerce.org/abc#MyMessage" 

<SOAP-ENV:Envelope... 

HTTP/1.1 200 OK 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

<SOAP-ENV:Envelope...

例4 使用擴充架構的SOAP HTTP

M-POST /StockQuote HTTP/1.1 

Man: "http://schemas.xmlsoap.org/soap/envelope/"; ns=NNNN 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

NNNN-SOAPAction: "http://electrocommerce.org/abc#MyMessage" 

<SOAP-ENV:Envelope... 

HTTP/1.1 200 OK 

Ext: 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

<SOAP-ENV:Envelope...

7. 在RPC中使用SOAP

設計SOAP的目的之一就是利用XML的擴充性和靈活性來封裝和交換RPC調用。這一節定義了遠端過程調用和應答的統一表示形式。雖然可以預計到這種表示形式最可能被用于與第5節中定義的編碼方式相結合,但也可能有其它的表示形式。SOAP的encodingStyle屬性(見4.3.2節)可以用來表明方法調用和應答都使用這一節所指定的表示方式。在RPC中使用SOAP和SOAP協定綁定(見第6節)是緊密相關的。在使用HTTP作為綁定協定時,一個RPC調用自然地映射到一個HTTP請求,RPC應答同樣映射到HTTP應答。但是,在RPC中使用SOAP并不限于綁定HTTP協定。 

要進行方法調用,以下的資訊是必需的:

  • 目标對象的URI
  • 方法名
  • 方法signature(可選)
  • 方法的參數
  • 頭資料(可選)

SOAP依靠協定綁定提供傳送URI的機制。例如,對HTTP來說,請求的URI指出了調用的來源 。除了必須是一個合法的URI之外,SOAP對一個位址的格式沒有任何限制。(更多URI的資訊參見 [4])

7.1 RPC和SOAP體

RPC方法調用和應答都包含在SOAP Body元素中(見4.3節),它們使用如下的表示形式:

  • 一個方法調用用一個結構表示
  • 一個方法調用被看作一個單個的結構,每個[in]和[in/out]參數有一個accessor。結構的名和類型與方法相同。每個[in]和[in/out]參數都被看作一個accessor,這個accessor的名和類型與參數的名和類型相對應。它們的出現順序和方法中定義的參數順序相同。
  • 一個方法應答用一個結構表示。
  • 一個方法應答被看作一個單個的結構,傳回值和每個[in]和[in/out]參數有一個accessor。第一個accessor是傳回值,之後是參數accessor,參數accessor的出現順序和方法中定義的參數順序相同。每個參數accessor的名稱和類型與參數的名稱和類型相對應。傳回值accessor的名稱并不重要。同樣,結構的名稱也不重要,不過,通常在方法名稱的後面加上字元串"Response"作為結構的名稱。

方法錯誤使用SOAP Fault元素(見4.4節)表示。如果綁定的協定有額外的規則表示錯誤,則這些規則也必須要遵從。正如上面所述,方法調用和應答結構可以按照第5節中規則編碼,或者用encodingStyle屬性(見4.1.1節)指定編碼方式。應用程式可以處理缺少參數的請求,但是可能傳回一個錯誤。因為傳回結果表示調用成功,錯誤表示調用失敗,是以,在方法應答中同時包含傳回結果和錯誤是錯誤的。

7.2 RPC和SOAP頭

在RPC編碼中,可能會有與方法請求有關但不是正規的方法signature的附加資訊。如果這樣,它必須作為SOAP頭元素的子元素。使用這種頭元素的一個例子是在消息中傳遞事務ID。由于事務ID不是方法signature的一部分,通常由底層的元件而不是應用程式代碼控制,是以沒有一種直接的方法在調用中傳遞這個必要的資訊。通過在頭中添加一個給定名字的條目,接收方的事務管理器就可以析取這個事務ID,而且不影響遠端過程調用的代碼。

8. 安全性考慮

這篇文檔中沒有涉及完整性和保密性,這些問題将在以後的版本中描述。

9. 參考文獻

[1] S. Bradner, "The Internet Standards Process -- Revision 3", RFC2026, Harvard University, October 1996 

[2] S. Bradner, "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, Harvard University, March 1997 

[3] E. Whitehead, M. Murata, "XML Media Types", RFC2376, UC Irvine, Fuji Xerox Info. Systems, July 1998 

[4] T. Berners-Lee, R. Fielding, L. Masinter, "Uniform Resource Identifiers (URI): Generic Syntax", RFC 2396, MIT/LCS, U.C.Irvine, Xerox Corporation, A ugust 1998. 

[5] R. Fielding, J. Gettys, J. C. Mogul, H. Frystyk, T. Berners-Lee, "Hypert ext Transfer Protocol -- HTTP/1.1", RFC 2616, U.C. Irvine, DEC W3C/MIT, DEC,W3C/MIT, W3C/MIT, January 1997 

[6] H. Nielsen, P. Leach, S. Lawrence, "An HTTP Extension Framework", RFC 2774, Microsoft, Microsoft, Agranat Systems 

[7] W3C Recommendation "The XML Specification"

[8] W3C Recommendation "Namespaces in XML" 

[9] W3C Working Draft "XML Linking Language". This is work in progress. 

[10] W3C Working Draft "XML Schema Part 1: Structures". This is work in progress. 

[11] W3C Working Draft "XML Schema Part 2: Datatypes". This is work in progress. 

[12] Transfer Syntax NDR, in "DCE 1.1: Remote Procedure Call" 

[13] N. Freed, N. Borenstein, "Multipurpose Internet Mail Extensions (MIME)Part One: Format of Internet Message Bodies", RFC2045, Innosoft, First Virtu al, November 1996

10。 附錄

A. SOAP封裝舉例

A.1 請求編碼舉例

例5 類似于例1,但有一個必要的頭

POST /StockQuote HTTP/1.1 

Host: www.stockquoteserver.com 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

SOAPAction: "Some-URI" 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 

<SOAP-ENV:Header> 

<t:Transaction 

xmlns:t="some-URI" 

SOAP-ENV:mustUnderstand="1"> 

</t:Transaction> 

</SOAP-ENV:Header> 

<SOAP-ENV:Body> 

<m:GetLastTradePrice xmlns:m="Some-URI"> 

<symbol>DEF</symbol> 

</m:GetLastTradePrice> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

例6 類似于例1,但有多個請求參數

POST /StockQuote HTTP/1.1 

Host: www.stockquoteserver.com 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

SOAPAction: "Some-URI" 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 

<SOAP-ENV:Body> 

<m:GetLastTradePriceDetailed 

xmlns:m="Some-URI"> 

<Symbol>DEF</Symbol> 

<Company>DEF Corp</Company> 

<Price>34.1</Price> 

</m:GetLastTradePriceDetailed> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

A.2 應答編碼舉例

例7 與例2類似,但有必要的頭部

HTTP/1.1 200 OK 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 

<SOAP-ENV:Header> 

<t:Transaction xmlns:t="some-URI" xsi:type="xsd:int" mustUnderstand="1"> 5 </t:Transaction> 

</SOAP-ENV:Header> 

<SOAP-ENV:Body> 

<m:GetLastTradePriceResponse xmlns:m="Some-URI"> 

<Price>34.5</Price> 

</m:GetLastTradePriceResponse> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

例8 與例2類似,但有一個結構

HTTP/1.1 200 OK 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> 

<SOAP-ENV:Body> 

<m:GetLastTradePriceResponse 

xmlns:m="Some-URI"> 

<PriceAndVolume> 

<LastTradePrice> 34.5 </LastTradePrice> 

<DayVolume> 10000 </DayVolume> 

</PriceAndVolume> 

</m:GetLastTradePriceResponse> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

例9 與例2類似,但處理必要的頭出錯

HTTP/1.1 500 Internal Server Error 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 

<SOAP-ENV:Body> 

<SOAP-ENV:Fault> 

<faultcode>SOAP-ENV:MustUnderstand</faultcode> 

<faultstring>SOAP Must Understand Error</faultstring> 

</SOAP-ENV:Fault> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

例10 與例2類似,但處理Body出錯

HTTP/1.1 500 Internal Server Error 

Content-Type: text/xml; charset="utf-8" 

Content-Length: nnnn 

<SOAP-ENV:Envelope 

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 

<SOAP-ENV:Body> 

<SOAP-ENV:Fault> 

<faultcode>SOAP-ENV:Server</faultcode> 

<faultstring>Server Error</faultstring> 

<detail> 

<e:myfaultdetails xmlns:e="Some-URI"> 

<message> 

My application didn't work 

</message> 

<errorcode> 1001 </errorcode> 

</e:myfaultdetails> 

</detail> 

</SOAP-ENV:Fault> 

</SOAP-ENV:Body> 

</SOAP-ENV:Envelope>

上一篇: OGC:Filter