24 Oracle XML Developer's Kit for CでのSOAPの使用
Simple Object Access Protocol (SOAP)をOracle XML Developer's Kit (XDK) for Cと組み合せて使用する方法について説明します。
トピック:
- SOAP for Cの概要
SOAPは、HTTPおよびHTTPSにより分散環境のピア間の構造化情報や入力情報を送受信するためのExtensible Markup Language (XML)プロトコルです。Oracle Database 10gリリース2用のXDKでは、HTTP 1.0のみサポートされています。 - SOAP C関数
SOAP Cの実装では、xml.h
ヘッダーが使用されます。SOAPコンテキストを作成する前に、xmlctx
タイプのコンテキストを作成する必要があります。 - SOAPの例1: XML文書の送信
旅行会社にJohn Smithのニューヨーク発ロサンゼルス行きの航空券を予約するリクエストを記述したXML文書を示します。この単純な例では、XML文書を作成して送信し、返信を受信および分解します。最小限のエラー・チェックが行われます。 - SOAPの例2: 明確化を求めるレスポンス
旅行会社は、旅行者John SmithがニューヨークのJFK、EWRまたはLGAのいずれの空港から出発するかを知る必要があります。この点について質問する返信メッセージを送信します。 - SOAPの例3: POSTの使用
この例では、メソッドPOST
を使用して、John Smithのクレジット・カード情報をXML文書として送信します。この例では、XmlSoapCall()
の実行により、XMLメッセージの前にHTTPヘッダーが記述されています。
関連項目:
24.1 SOAP for Cの概要
SOAPは、HTTPおよびHTTPSにより分散環境のピア間の構造化情報や入力情報を送受信するためのExtensible Markup Language (XML)プロトコルです。Oracle Database 10gリリース2用のXDKでは、HTTP 1.0のみサポートされています。
SOAPは次の3つの部分に分かれています。
-
メッセージ内容の表示方法、メッセージの処理者、処理の任意または必須を定義するSOAPエンベロープ。
-
アプリケーションのデータ型をXMLへ、またXMLをアプリケーションのデータ型へ変換するためのシリアライズおよびデシリアライズ・ルール。
-
コールとレスポンスを定義するSOAPリモート・プロシージャ・コール(RPC)。
注意:
RPCとシリアライズおよびデシリアライズはこのリリースではサポートされません。
SOAPはXMLを使用するため、オペレーティング・システムや言語に依存しません。この章では、SOAPメッセージの読取りや書込みを行う関数のC実装について説明します。
SOAPバージョン1.2は、メッセージ内容を説明するXML Information Set(抽象データセット、XML 1.0も使用可)として指定されるXMLベースのメッセージ定義です。バージョン1.1もサポートされています。
トピック:
- SOAPメッセージの概要
SOAPは、リクエストおよびレスポンスをインターネット経由で送受信するための軽量プロトコルです。このプロトコルはXMLおよび転送プロトコル(HTTPなど)に基づくもので、多くの場合、ファイアウォールによってブロックされません。SOAPはオペレーティング・システム、実装言語およびオブジェクト・モデルに依存しません。 - SOAPクライアントの使用
SOAPクライアントはXML文書を生成するユーザー作成アプリケーションです。それらの文書でSOAPサービスへのリクエストを行い、SOAPレスポンスを処理します。XDKのSOAP実装は、有効なSOAPリクエストを送信するすべてのクライアントからのリクエストを処理します。 - SOAPサーバーの使用
SOAPサービス・リクエストの実行時にSOAPサーバーによって実行される手順について説明します。
24.1.1 SOAPメッセージの概要
SOAPは、リクエストおよびレスポンスをインターネット経由で送受信するための軽量プロトコルです。このプロトコルはXMLおよび転送プロトコル(HTTPなど)に基づくもので、多くの場合、ファイアウォールによってブロックされません。SOAPはオペレーティング・システム、実装言語およびオブジェクト・モデルに依存しません。
SOAPの長所は、異種ソフトウェア・コンポーネント間の連結機能にあります。たとえば、Visual BasicクライアントからUNIXコンピュータ上で動作するCommon Object Request Broker Architecture (CORBA)サービスを起動したり、MacintoshクライアントからLinux上で動作するPerlオブジェクトを起動したりできます。
SOAPメッセージは次の部分に分かれています。
-
エンベロープ: メッセージを含み、その処理方法、処理者、およびその処理がオプションか必須かを指定します。
Envelope
要素は必須です。 -
エンコーディング規則: アプリケーションで使用するデータ型を記述します。これらの規則では、アプリケーションのデータ型をXMLへ、またXMLをデータ型へ変換するシリアライズ・メカニズムが定義されます。
-
リモート・プロシージャ・コール(RPC): リクエストおよびレスポンスの規則を定義します。この必須要素は本体要素と呼ばれます。
Body
要素には、メソッド名を名前とする最初のサブ要素を指定します。このメソッド・リクエスト要素には、各入出力パラメータの要素が含まれます。要素名はパラメータ名です。RPCはこのリリースではサポートされていません。
SOAPは転送プロトコルに依存しません。ただし、HTTPによるリモート・サービスの起動に使用されるSOAPが、プログラミングされたコンテンツをインターネット上で提供するための標準として扱われています。
SOAPは、転送プロトコルに依存しないだけでなく、オペレーティング・システムにも依存しません。そのため、SOAPを使用すると、プログラムが異なる言語で記述されている場合や、異なるオペレーティング・システム上で実行される場合にも通信が可能です。
トピック:
- SOAPメッセージの書式
SOAPメッセージのタイプについて説明します。
24.1.1.1 SOAPメッセージの書式
SOAPメッセージのタイプについて説明します。
-
サービスのリクエスト(入力パラメータを含む)
-
リクエストされたサービスからのレスポンス(戻り値および出力パラメータを含む)
-
エラー・コードおよびエラー情報を含むオプションのFault要素
SOAPのメッセージでは、ペイロードにXML用にエンコードされたデータが含まれます。処理情報は含まれません。メッセージ・ヘッダーには処理情報が含まれる場合があります。
トピック:
- SOAPリクエスト
SOAPリクエストについて説明します。 - SOAPレスポンスの例
SOAPレスポンスの例を示します。
24.1.1.1.1 SOAPリクエスト
SOAPリクエストについて説明します。
SOAPリクエストでは、XMLペイロードに次のような要素が含まれます。
-
ルート要素
-
メソッド要素
-
ヘッダー要素(オプション)
例24-1に、サンプルSOAPメッセージ・リクエストの書式を示します。GetLastTradePrice
SOAPリクエストをStockQuote
サービスに送信します。このリクエストは企業の銘柄記号を示す文字列パラメータを取り、SOAPレスポンスで株価を示すfloat型を戻します。
例24-1 SOAPリクエスト・メッセージ
POST /StockQuote HTTP/1.0 Host: www.stockquoteserver.com Content-Type: application/soap+xml; charset="utf-8" Content-Length: nnnn SOAPAction: "Some-URI" <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" SOAP-ENV:encodingStyle="http://www.w3.org/2003/05/soap-encoding/"> <SOAP-ENV:Body> <m:GetLastTradePrice xmlns:m="Some-URI"> <symbol>ORCL</symbol> <m:GetLastTradePrice> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
例24-1のXML文書はSOAPメッセージです。<SOAP-ENV:Envelope>
要素は、XML文書の最上位要素です。ペイロードはメソッド要素<m:GetLastTradePrice>
で示されます。XML名前空間を使用して、SOAP識別子とアプリケーション固有の識別子を区別します。
ヘッダーの最初の行では、リクエストの転送プロトコルにHTTPを使用することが指定されています。
POST /StockQuote HTTP/1.1
SOAPは転送プロトコルに依存しないため、XMLペイロード形式を決定する規則は、このペイロードがHTTPで転送されるということには関係ありません。このHTTPリクエストはURI /StockQuote
を指しています。SOAP仕様ではコンポーネントのアクティブ化の問題を処理しないため、このURIでコンポーネントのアクティブ化方法とGetLastTradePrice
メソッドの起動方法を指定します。
24.1.1.1.2 SOAPレスポンスの例
SOAPレスポンスの例を示します。
例24-2に、例24-1のリクエストに対するレスポンスの書式を示します。要素<Price>
には、最初のメッセージでリクエストされたORCL
の株価が含まれています。
例24-1および例24-2のメッセージは、双方向のSOAPメッセージ(SOAPリクエストがSOAPレスポンスで応答される)を示しています。一方向のSOAPメッセージにはSOAPレスポンス・メッセージは不要です。
例24-2 SOAPレスポンス・メッセージ
HTTP/1.0 200 OK
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
SOAP-ENV:encodingStyle="http://www.w3.org/2003/05/soap-encoding/">
<SOAP-ENV:Body>
<m:GetLastTradePriceResponse xmlns:m="Some-URI">
<Price>13.5</Price>
</m:GetLastTradePriceResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
24.1.2 SOAPクライアントの使用
SOAPクライアントはXML文書を生成するユーザー作成アプリケーションです。それらの文書でSOAPサービスへのリクエストを行い、SOAPレスポンスを処理します。XDKのSOAP実装は、有効なSOAPリクエストを送信するすべてのクライアントからのリクエストを処理します。
SOAPクライアント・アプリケーション・プログラミング・インタフェース(API)には次の機能があります。
-
リクエストおよびレスポンス用の同期式起動モデルをサポートします。
-
SOAPリクエストを行うクライアント・アプリケーションの作成を簡素化します。
-
SOAPリクエストの作成および基礎となる転送プロトコルを使用したリクエスト送信の詳細をカプセル化します。
-
プラガブルな転送をサポートし、クライアントは転送を簡単に変更できます(HTTPおよびHTTPSによる転送が可能ですが、このリリースでサポートされるのはHTTP 1.0のみです)。
SOAPクライアントでリクエストの送信やレスポンスの受信を行うには、次の手順を実行する必要があります。
- サービスの起動にすべての必要なパラメータを収集します。
- SOAPプロトコルに従って作成されるXMLメッセージである、SOAPサービスのリクエスト・メッセージを作成します。これは、XMLでエンコードされたすべての入力パラメータのすべての値を含みます。このプロセスをシリアライズと呼びます。
- SOAPサーバーがサポートする転送プロトコルを使用してリクエストをSOAPサーバーに送信します。
- SOAPレスポンス・メッセージを受信します。
- SOAP Fault要素を処理して、リクエストの成否を判断します。
- XMLから戻されたパラメータをネイティブなデータ型に変換します。このプロセスをデシリアライズといいます。
- 必要に応じて結果を使用します。
24.2 SOAP C関数
SOAP Cの実装では、xml.h
ヘッダーが使用されます。SOAPコンテキストを作成する前に、xmlctx
タイプのコンテキストを作成する必要があります。
SOAPのHTTP要素はユーザーからは見えません。SOAPエンドポイントは、組合せ(バインディング、エンドポイント)で指定されます。ここで、バインディングはxmlsoapbind
タイプ、バインディングに応じたエンドポイントは(void *
)です。現在サポートされているバインディングは、XMLSOAP_BIND_HTTP
のみです。HTTPバインディングの場合、エンドポイントは(OraText *
) URLです。
SOAPレイヤーでエンドポイント間のSOAPメッセージが作成および転送され、受信したSOAPメッセージが分解されます。
C関数はxmlsoap.h
で宣言します。次に、ヘッダー・ファイルの開始部分を示します。
関連項目:
C SOAP APIについては、『Oracle Database XML C APIリファレンス』を参照してください
例24-3 xmlsoap.hに定義されたSOAP C関数
FILE NAME xmlsoap.h - XML SOAP APIs FILE DESCRIPTION XML SOAP Public APIs PUBLIC FUNCTIONS XmlSoapCreateCtx - Create and return a SOAP context XmlSoapDestroyCtx - Destroy a SOAP context XmlSoapCreateConnection - Create a SOAP connection object XmlSoapDestroyConnection - Destroy a SOAP connection object XmlSoapCall - Send a SOAP message & wait for reply XmlSoapCreateMsg - Create and return an empty SOAP message XmlSoapDestroyMsg - Destroy a SOAP message created w/XmlSoapCreateMsg XmlSoapGetEnvelope - Return a SOAP message's envelope XmlSoapGetHeader - Return a SOAP message's envelope header XmlSoapGetBody - Return a SOAP message's envelope body XmlSoapAddHeaderElement - Adds an element to a SOAP header XmlSoapGetHeaderElement - Gets an element from a SOAP header XmlSoapAddBodyElement - Adds an element to a SOAP message body XmlSoapGetBodyElement - Gets an element from a SOAP message body XmlSoapSetMustUnderstand - Set mustUnderstand attr for SOAP hdr elem XmlSoapGetMustUnderstand - Get mustUnderstand attr from SOAP hdr elem XmlSoapSetRole - Set role for SOAP header element XmlSoapGetRole - Get role from SOAP header element XmlSoapSetRelay - Set relay Header element property XmlSoapGetRelay - Get relay Header element property XmlSoapSetFault - Set Fault in SOAP message XmlSoapHasFault - Does SOAP message have a Fault? XmlSoapGetFault - Return Fault code, reason, and details XmlSoapAddFaultReason - Add additional Reason to Fault XmlSoapAddFaultSubDetail - Add additional child to Fault Detail XmlSoapGetReasonNum - Get number of Reasons in Fault element XmlSoapGetReasonLang - Get a lang of a reasons with a particular iindex. XmlSoapError - Get error message(s) */ #ifndef XMLSOAP_ORACLE # define XMLSOAP_ORACLE # ifndef XML_ORACLE # include <xml.h> # endif /*--------------------------------------------------------------------------- Package SOAP - Simple Object Access Protocol APIs W3C: "SOAP is a lightweight protocol for exchange of information in a decentralized, distributed environment. It is an XML based protocol that consists of three parts: an envelope that defines a framework for describing what is in a message and how to process it, a set of encoding rules for expressing instances of application-defined datatypes, and a convention for representing remote procedure calls and responses." Atachments are allowed only in Soap 1.1 In Soap 1.2 body may not have other elements if Fault is present. Structure of a SOAP message: [SOAP message (XML document) [SOAP envelope [SOAP header? element* ] [SOAP body (element* | Fault)? ] ] ] ---------------------------------------------------------------------------*/ ...
24.3 SOAPの例1: XML文書の送信
旅行会社にJohn Smithのニューヨーク発ロサンゼルス行きの航空券を予約するリクエストを記述したXML文書を示します。この単純な例では、XML文書を作成して送信し、返信を受信および分解します。最小限のエラー・チェックが行われます。
エラーを修正するDEBUG
オプションが示されています。このプログラムは、すべてのオペレーティング・システムで動作するとはかぎりません。このXML文書を送信するには、クライアントのCプログラムで次の手順を実行します。
-
main()
で変数を宣言した後、XMLコンテキスト、xctx
をXmlCreate()
で作成し、このコンテキストを使用してSOAPコンテキスト、ctx
をXmlSoapCreateCtx()
で作成します。 -
メッセージを作成するために
XmlSoapCreateMsg()
をコールすると、空のSOAPメッセージが戻されます。 -
ヘッダーを
XmlSoapAddHeaderElement()
、XmlSoapSetRole()
、XmlSoapSetMustUnderstand()
およびXmlDomAddTextElem()
で作成して、エンベロープにテキストを指定します。 -
本体要素を
XmlSoapAddBodyElement()
、XmlDomCreateElemNS()
および一連のXmlDomAddTextElem()
の起動によって作成します。次に、XmlDomAppendChild()
を追加すれば、ニューヨーク発ロサンゼルス行きの便を指定する本体のセクションが完成します。 -
帰りの航空券についても同様の方法で作成します。宿泊先を新たな
XmlSoapAddBodyElement()
の起動で追加します。 -
次に、
XmlSoapCreateConnection()
で接続を作成し、HTTPバインディング(現時点で使用可能な唯一のバインディング)とエンドポイントのURLを指定する必要があります。 -
XmlSoapCall()
関数で、SOAPサーバーを使用して定義済の接続でメッセージを送信し、リプライを待機します。 -
メッセージ返信は別のSOAPメッセージの形式で戻されます。それには、
XmlSaveDom()
とXmlSoapHasFault()
をXmlSoapGetFault()
とともに使用して、フォルトをチェックし、分析します。フォルトを解析して各部分に分けます。その出力結果がこの例です。 -
フォルトが戻されなければ、次の
XmlSoapGetBody()
でエンベロープの本体が戻されます。XmlSaveDom()
を実行すると、戻されたメッセージの分析が完了します。 -
クリーンアップするには、メッセージとリプライのそれぞれに対して
XmlSoapDestroyMsg()
を実行し、XmlDestroyCtx()
でSOAPコンテキストを削除し、XmlDestroy()
でXMLコンテキストを削除します。
例24-4 例1 SOAPメッセージ
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
<m:reservation xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
</m:reservation>
<n:passenger xmlns:n="http://mycompany.example.com/employees"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<n:name>John Smith</n:name>
</n:passenger>
</env:Header>
<env:Body>
<p:itinerary
xmlns:p="http://travelcompany.example.org/reservation/travel">
<p:departure>
<p:departing>New York</p:departing>
<p:arriving>Los Angeles</p:arriving>
<p:departureDate>2001-12-14</p:departureDate>
<p:departureTime>late afternoon</p:departureTime>
<p:seatPreference>aisle</p:seatPreference>
</p:departure>
<p:return>
<p:departing>Los Angeles</p:departing>
<p:arriving>New York</p:arriving>
<p:departureDate>2001-12-20</p:departureDate>
<p:departureTime>mid-morning</p:departureTime>
<p:seatPreference/>
</p:return>
</p:itinerary>
<q:lodging
xmlns:q="http://travelcompany.example.org/reservation/hotels">
<q:preference>none</q:preference>
</q:lodging>
</env:Body>
</env:Envelope>
例24-5 例1 SOAP Cクライアント
#ifndef S_ORACLE
# include <s.h>
#endif
#ifndef XML_ORACLE
# include <xml.h>
#endif
#ifndef XMLSOAP_ORACLE
# include <xmlsoap.h>
#endif
#define MY_URL "http://my_url.com"
/* static function declaration */
static xmlerr add_ns_decl(xmlsoapctx *ctx, xmlctx *xctx, xmlelemnode *elem,
oratext *pfx, oratext *uri);
sb4 main( sword argc, char *argv[])
{
xmlctx *xctx;
xmlerr xerr;
xmlsoapctx *ctx;
oratext *url;
xmlsoapcon *con;
xmldocnode *msg1, *reply, *msg2, *msg3;
xmlelemnode *res, *pas, *pref, *itin, *departure, *ret, *lodging;
xmlelemnode *departing, *arriving, *trans, *text, *charge, *card, *name;
xmlelemnode *body, *header;
boolean has_fault;
oratext *code, *reason, *lang, *node, *role;
xmlelemnode *detail;
oratext *comp_uri = "http://travelcompany.example.org/";
oratext *mres_uri = "http://travelcompany.example.org/reservation";
oratext *trav_uri = "http://travelcompany.example.org/reservation/travel";
oratext *hotel_uri = "http://travelcompany.example.org/reservation/hotels";
oratext *npas_uri = "http://mycompany.example.com/employees";
oratext *tparty_uri = "http://thirdparty.example.org/transaction";
oratext *estyle_uri = "http://example.com/encoding";
oratext *soap_style_uri = "http://www.w3.org/2003/05/soap-encoding";
oratext *estyle = "env:encodingStyle";
oratext *finance_uri = "http://mycompany.example.com/financial";
if (!(xctx = XmlCreate(&xerr, (oratext *)"SOAP_test",NULL)))
{
printf("Failed to create XML context, error %u\n", (unsigned) xerr);
return EX_FAIL;
}
/* Create SOAP context */
if (!(ctx = XmlSoapCreateCtx(xctx, &xerr, (oratext *) "example", NULL)))
{
printf("Failed to create SOAP context, error %u\n", (unsigned) xerr);
return EX_FAIL;
}
/* EXAMPLE 1 */
/* construct message */
if (!(msg1 = XmlSoapCreateMsg(ctx, &xerr)))
{
printf("Failed to create SOAP message, error %u\n", (unsigned) xerr);
return xerr;
}
res = XmlSoapAddHeaderElement(ctx, msg1, "m:reservation", mres_uri, &xerr);
xerr = XmlSoapSetRole(ctx, res, XMLSOAP_ROLE_NEXT);
xerr = XmlSoapSetMustUnderstand(ctx, res, TRUE);
(void) XmlDomAddTextElem(xctx, res, mres_uri, "m:reference",
"uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d");
(void) XmlDomAddTextElem(xctx, res, mres_uri, "m:dateAndTime",
"2001-11-29T13:20:00.000-05:00");
pas = XmlSoapAddHeaderElement(ctx, msg1, "n:passenger", npas_uri, &xerr);
xerr = XmlSoapSetRole(ctx, pas, XMLSOAP_ROLE_NEXT);
xerr = XmlSoapSetMustUnderstand(ctx, pas, TRUE);
(void) XmlDomAddTextElem(xctx, pas, npas_uri, "n:name",
"John Smith");
/* Fill body */
/* Itinerary */
itin = XmlSoapAddBodyElement(ctx, msg1, "p:itinerary", trav_uri, &xerr);
/* Departure */
departure = XmlDomCreateElemNS(xctx, msg1, trav_uri, "p:departure");
(void) XmlDomAddTextElem(xctx, departure, trav_uri,
"p:departing","New York");
(void) XmlDomAddTextElem(xctx, departure, trav_uri,
"p:arriving", "Los Angeles");
(void) XmlDomAddTextElem(xctx, departure, trav_uri,
"p:departureDate", "2001-12-14");
(void) XmlDomAddTextElem(xctx, departure, trav_uri,
"p:departureTime", "late afternoon");
(void) XmlDomAddTextElem(xctx, departure, trav_uri,
"p:seatPreference", "aisle");
XmlDomAppendChild(xctx, itin, departure);
/* Return */
ret = XmlDomCreateElemNS(xctx, msg1, trav_uri, "p:return");
(void) XmlDomAddTextElem(xctx, ret, trav_uri,
"p:departing", "Los Angeles");
(void) XmlDomAddTextElem(xctx, ret, trav_uri,
"p:arriving", "New York");
(void) XmlDomAddTextElem(xctx, ret, trav_uri,
"p:departureDate", "2001-12-20");
(void) XmlDomAddTextElem(xctx, ret, trav_uri,
"p:departureTime", "mid-morning");
pref = XmlDomCreateElemNS(xctx, msg1, trav_uri, "p:seatPreference");
(void) XmlDomAppendChild(xctx, ret, pref);
XmlDomAppendChild(xctx, itin, ret);
/* Lodging */
lodging = XmlSoapAddBodyElement(ctx, msg1, "q:lodging", hotel_uri, &xerr);
(void) XmlDomAddTextElem(xctx, lodging, hotel_uri,
"q:preference", "none");
#ifdef DEBUG
/* dump the message in debug mode */
printf("Message:\n");
XmlSaveDom(xctx, &xerr, msg1, "stdio", stdout, "indent_step", 1, NULL);
#endif
/* END OF EXAMPLE 1 */
/* create connection */
url = MY_URL;
if (!(con = XmlSoapCreateConnection(ctx, &xerr, XMLSOAP_BIND_HTTP,
url, NULL, 0, NULL, 0,
"XTest: baz", NULL)))
{
printf("Failed to create SOAP connection, error %u\n", (unsigned) xerr);
return xerr;
}
reply = XmlSoapCall(ctx, con, msg1, &xerr);
XmlSoapDestroyConnection(ctx, con);
if (!reply)
{
printf("Call failed, no message returned.\n");
return xerr;
}
#ifdef DEBUG
printf("Reply:\n");
XmlSaveDom(xctx, &xerr, reply, "stdio", stdout, NULL);
#endif
printf("\n==== Header:\n ");
header = XmlSoapGetHeader(ctx, reply, &xerr);
if (!header)
{
printf("NULL\n");
}
else
XmlSaveDom(xctx, &xerr, header, "stdio", stdout, NULL);
/* check for fault */
has_fault = XmlSoapHasFault(ctx, reply, &xerr);
if(has_fault)
{
lang = NULL;
xerr = XmlSoapGetFault(ctx, reply, &code, &reason, &lang,
&node, &role, &detail);
if (xerr)
{
printf("error getting Fault %d\n", xerr);
return EX_FAIL;
}
if(code)
printf(" Code -- %s\n", code);
else
printf(" NO Code\n");
if(reason)
printf(" Reason -- %s\n", reason);
else
printf(" NO Reason\n");
if(lang)
printf(" Lang -- %s\n", lang);
else
printf(" NO Lang\n");
if(node)
printf(" Node -- %s\n", node);
else
printf(" NO Node\n");
if(role)
printf(" Role -- %s\n", role);
else
printf(" NO Role\n");
if(detail)
{
printf(" Detail\n");
XmlSaveDom(xctx, &xerr, detail, "stdio", stdout, NULL);
printf("\n");
}
else
printf(" NO Detail\n");
}
else
{
body = XmlSoapGetBody(ctx, reply, &xerr);
printf("==== Body:\n ");
if (!body)
{
printf("NULL\n");
return EX_FAIL;
}
XmlSaveDom(xctx, &xerr, body, "stdio", stdout, NULL);
}
(void) XmlSoapDestroyMsg(ctx, reply);
(void) XmlSoapDestroyMsg(ctx, msg1);
(void) XmlSoapDestroyCtx(ctx);
XmlDestroy(xctx);
}
24.4 SOAPの例2: 明確化を求めるレスポンス
旅行会社は、旅行者John Smithがニューヨークのどの空港(JFK、EWRまたはLGA)から出発するかを知る必要があります。この点について質問する返信メッセージを送信します。
このXML文書をSOAPメッセージとして送信するには、例24-5の/* EXAMPLE 1 */
から/* END OF EXAMPLE 1 */
までの行を次のコード・ブロックに置き換えます
例24-6 例2 SOAPメッセージ
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
<m:reservation xmlns:m="http://travelcompany.example.org/reservation"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
<m:dateAndTime>2001-11-29T13:35:00.000-05:00</m:dateAndTime>
</m:reservation>
<n:passenger xmlns:n="http://mycompany.example.com/employees"
env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
env:mustUnderstand="true">
<n:name>John Smith</n:name>
</n:passenger>
</env:Header>
<env:Body>
<p:itineraryClarification
xmlns:p="http://travelcompany.example.org/reservation/travel">
<p:departure>
<p:departing>
<p:airportChoices>
JFK LGA EWR
</p:airportChoices>
</p:departing>
</p:departure>
<p:return>
<p:arriving>
<p:airportChoices>
JFK LGA EWR
</p:airportChoices>
</p:arriving>
</p:return>
</p:itineraryClarification>
</env:Body>
</env:Envelope>
例24-7 例2 SOAP Cクライアント
#define XMLSOAP_MAX_NAME 1024
/* we need this function for examples 2 and 3 */
static xmlerr add_ns_decl(xmlsoapctx *ctx, xmlctx *xctx, xmlelemnode *elem,
oratext *pfx, oratext *uri)
{
oratext *aq, aqbuf[XMLSOAP_MAX_NAME];
xmldocnode *doc;
oratext *xmlns = "xmlns:";
/* if no room for "xmlns:usersprefix\0" then fail now */
if ((strlen((char *)pfx) + strlen((char *)xmlns)) >
sizeof(aqbuf))
return EX_FAIL;
(void) strcpy((char *)aqbuf, (char *)xmlns);
strcat((char *)aqbuf, (char *)pfx);
doc = XmlDomGetOwnerDocument(xctx, elem);
aq = XmlDomSaveString(xctx, doc, aqbuf);
XmlDomSetAttrNS(xctx, elem, uri, aq, uri);
return XMLERR_OK;
}
/* EXAMPLE 2 */
/* construct message */
if (!(msg2 = XmlSoapCreateMsg(ctx, &xerr)))
{
printf("Failed to create SOAP message, error %u\n", (unsigned) xerr);
return xerr;
}
res = XmlSoapAddHeaderElement(ctx, msg2, "m:reservation", mres_uri, &xerr);
xerr = XmlSoapSetRole(ctx, res, XMLSOAP_ROLE_NEXT);
xerr = XmlSoapSetMustUnderstand(ctx, res, TRUE);
(void) XmlDomAddTextElem(xctx, res, mres_uri, "m:reference",
"uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d");
(void) XmlDomAddTextElem(xctx, res, mres_uri, "m:dateAndTime",
"2001-11-29T13:35:00.000-05:00");
pas = XmlSoapAddHeaderElement(ctx, msg2, "n:passenger", npas_uri, &xerr);
xerr = XmlSoapSetRole(ctx, pas, XMLSOAP_ROLE_NEXT);
xerr = XmlSoapSetMustUnderstand(ctx, pas, TRUE);
(void) XmlDomAddTextElem(xctx, pas, npas_uri, "n:name",
"John Smith");
/* Fill body */
/* Itinerary */
itin = XmlSoapAddBodyElement(ctx, msg2, "p:itineraryClarification",
trav_uri, &xerr);
/* Departure */
departure = XmlDomCreateElemNS(xctx, msg2, trav_uri, "p:departure");
departing = XmlDomCreateElem(xctx, msg2, "p:departing");
(void) XmlDomAddTextElem(xctx, departing, trav_uri,
"p:airportChoices", "JFK LGA EWR");
(void) XmlDomAppendChild(xctx, departure, departing);
XmlDomAppendChild(xctx, itin, departure);
/* Return */
ret = XmlDomCreateElemNS(xctx, msg2, trav_uri, "p:return");
arriving = XmlDomCreateElemNS(xctx, msg2, trav_uri, "p:arriving");
(void) XmlDomAddTextElem(xctx, arriving, trav_uri,
"p:airportChoices", "JFK LGA EWR");
XmlDomAppendChild(xctx, ret, arriving);
XmlDomAppendChild(xctx, itin, ret);
#ifdef DEBUG
XmlSaveDom(xctx, &xerr, msg2, "stdio", stdout, "indent_step", 1, NULL);
#endif
24.5 SOAPの例3: POSTの使用
この例では、メソッドPOST
を使用して、John Smithのクレジット・カード情報をXML文書として送信します。この例では、XmlSoapCall()
の実行により、XMLメッセージの前にHTTPヘッダーが記述されています。
Cクライアントでは、例24-5の2番目の例と同じ箇所を次のコード・ブロックに置き換えます。
例24-8 例3 SOAPメッセージ
POST /Reservations HTTP/1.0
Host: travelcompany.example.org
Content-Type: application/soap+xml; charset="utf-8"
Content-Length: nnnn
<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
<env:Header>
<t:transaction
xmlns:t="http://thirdparty.example.org/transaction"
env:encodingStyle="http://example.com/encoding"
env:mustUnderstand="true" >5</t:transaction>
</env:Header>
<env:Body>
<m:chargeReservation
env:encodingStyle="http://www.w3.org/2003/05/soap-encoding"
xmlns:m="http://travelcompany.example.org/">
<m:reservation xmlns:m="http://travelcompany.example.org/reservation">
<m:code>FT35ZBQ</m:code>
</m:reservation>
<o:creditCard xmlns:o="http://mycompany.example.com/financial">
<n:name xmlns:n="http://mycompany.example.com/employees">
John Smith
</n:name>
<o:number>123456789099999</o:number>
<o:expiration>2005-02</o:expiration>
</o:creditCard>
</m:chargeReservation>
</env:Body>
</env:Envelope>
例24-9 例3 SOAP Cクライアント
#define XMLSOAP_MAX_NAME 1024
/* we need this function for examples 2 and 3 */
static xmlerr add_ns_decl(xmlsoapctx *ctx, xmlctx *xctx, xmlelemnode *elem,
oratext *pfx, oratext *uri)
{
oratext *aq, aqbuf[XMLSOAP_MAX_NAME];
xmldocnode *doc;
oratext *xmlns = "xmlns:";
/* if no room for "xmlns:usersprefix\0" then fail now */
if ((strlen((char *)pfx) + strlen((char *)xmlns)) >
sizeof(aqbuf))
return EX_FAIL;
(void) strcpy((char *)aqbuf, (char *)xmlns);
strcat((char *)aqbuf, (char *)pfx);
doc = XmlDomGetOwnerDocument(xctx, elem);
aq = XmlDomSaveString(xctx, doc, aqbuf);
XmlDomSetAttrNS(xctx, elem, uri, aq, uri);
return XMLERR_OK;
}
/* EXAMPLE 3 */
if (!(msg3 = XmlSoapCreateMsg(ctx, &xerr)))
{
printf("Failed to create SOAP message, error %u\n", (unsigned) xerr);
return xerr;
}
trans = XmlSoapAddHeaderElement(ctx,msg3, "t:transaction", tparty_uri, &xerr);
xerr = XmlSoapSetMustUnderstand(ctx, trans, TRUE);
XmlDomSetAttr(xctx, trans, estyle, estyle_uri);
text = XmlDomCreateText(xctx, msg3, "5");
XmlDomAppendChild(xctx, trans, text);
/* Fill body */
/* Charge Reservation */
charge = XmlSoapAddBodyElement(ctx,msg3,"m:chargeReservation",comp_uri,&xerr);
XmlDomSetAttr(xctx, charge, estyle, soap_style_uri);
res = XmlDomCreateElemNS(xctx, msg3, mres_uri, "m:reservation");
if (add_ns_decl(ctx, xctx, res, "m", mres_uri))
return EX_FAIL;
(void) XmlDomAddTextElem(xctx, res, mres_uri,
"m:code", "FT35ZBQ");
(void) XmlDomAppendChild(xctx, charge, res);
/* create card elem with namespace */
card = XmlDomCreateElemNS(xctx, msg3, finance_uri, "o:creditCard");
if (add_ns_decl(ctx, xctx, card, "o", finance_uri))
return EX_FAIL;
name = XmlDomAddTextElem(xctx, card, npas_uri,
"n:name", "John Smith");
/* add namespace */
if (add_ns_decl(ctx, xctx, name, "n", npas_uri))
return EX_FAIL;
(void) XmlDomAddTextElem(xctx, card, finance_uri,
"o:number", "123456789099999");
(void) XmlDomAddTextElem(xctx, card, finance_uri,
"o:expiration", "2005-02");
(void) XmlDomAppendChild(xctx, charge, card);
#ifdef DEBUG
XmlSaveDom(xctx, &xerr, msg3, "stdio", stdout, "indent_step", 1, NULL);
#endif