首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

C 語言 gSOAP 實戰:將資料序列化為 XML 輸出 (soap_out vs soap_put 詳解)

     編輯:關於C

前言:gSOAP 的兩種輸出 API

gSOAP 為每種資料型別產生兩組序列化函式:

  • soap_out_TYPE:**可重複呼叫**,支援多次輸出同類型資料,需手動管理 id 區分實例
  • soap_put_TYPE:**單次輸出**,內部呼叫 soap_out + soap_putindependent,自動處理獨立元素封裝

理解兩者差異,才能正確產出符合 SOAP 規範的 XML。

核心差異對比

特性soap_out_TYPEsoap_put_TYPE
呼叫次數可多次單次 (後續呼叫會覆蓋/錯誤)
id 參數手動指定 (如 1, 2, "myid")內部自動管理
XML 輸出含 id="..." 屬性無 id 屬性 (獨立元素)
適用場景陣列、重複結構、需引用單一獨立值、簡單回傳
前置需求需先 soap_serialize_TYPE內含序列化 (基本型別除外)

基本型別輸出範例

1. 整數

struct soap *soap = soap_new();
int num = 12345;

// 方式 A: soap_put (單次、簡單)
soap_put_int(soap, &num, "myint", NULL);
// 輸出:
// 
// 12345

// 方式 B: soap_out (多次、需 id)
soap_out_int(soap, "myint", 1, &num, NULL);
soap_out_int(soap, "myint", 2, &num, NULL);
// 輸出:
// 
// 1234512345

2. 字串 (需先序列化)

char *str = "hehe";

// soap_put: 內部會處理序列化
soap_put_string(soap, &str, "mystring", NULL);
// hehe

// soap_out: 必須先序列化
soap_serialize_string(soap, &str);
soap_out_string(soap, "mystring", 1, &str, NULL);
soap_out_string(soap, "mystring", 2, &str, NULL);
// hehehehe

複雜型別:自訂結構體輸出

步驟

  1. 在 .h 定義結構體,加上 gSOAP 註解
  2. 執行 soapcpp2 產生序列化代碼
  3. 使用產生的 soap_serialize_、soap_put_/soap_out_

範例:LogInfo 結構體

// soapH.h (由 soapcpp2 產生)
struct LogInfo {
    char *content;
    int id;
};

// 使用
struct LogInfo loginfo = {"哈哈", 1};

// 單次輸出
soap_serialize_LogInfo(soap, &loginfo);
soap_put_LogInfo(soap, &loginfo, "logs", NULL);
// 輸出:
// 
//   哈哈
//   1
// 

// 多次輸出
soap_serialize_LogInfo(soap, &loginfo);
soap_out_LogInfo(soap, "logs", 1, &loginfo, NULL);
soap_out_LogInfo(soap, "logs", 2, &loginfo, NULL);
// 輸出:
// 哈哈1
// 哈哈1

完整最小化範例:HTTP 回應輸出 XML

#include "soapH.h"
#include "soapStub.h"

int main() {
    struct soap *soap = soap_new1(SOAP_XML_INDENT);  // 美化縮排
    soap->mode |= SOAP_XML_INDENT;

    // 設定 HTTP 標頭 (若為 CGI/Server)
    // soap->http_content = "text/xml; charset=utf-8";

    int num = 42;
    soap_put_int(soap, &num, "answer", NULL);

    // 將 XML 寫入 stdout (CGI) 或檔案
    soap_dump(soap, stdout);  // 或 soap_send(soap) 送出 HTTP 回應

    soap_destroy(soap);
    soap_end(soap);
    soap_free(soap);
    return 0;
}

關鍵細節避坑指南

  1. 基本型別 (int, float, enum) 不需 soap_serialize,結構體、字串、陣列、指標**必須先序列化**。
  2. 字串編碼:gSOAP 預設 UTF-8,確保源碼與終端機編碼一致,或用 soap->mode |= SOAP_XML_CANONICAL。
  3. 命名空間:soapcpp2 產生的代碼會依 .h 中註解加入 xmlns,客戶端需對應。
  4. 記憶體管理:soap_new() 分配 context,**必須成對呼叫 soap_destroy/end/free**,否則洩漏。
  5. 錯誤處理:每個 soap 函式回傳 soap->error,非 0 即失敗,需檢查 soap_print_fault(soap, stderr)。

soap_out 多次輸出的 id 機制

id 參數用於 XML 中的 href/id 參考機制 (SOAP Section 5 encoding):

  • id = 0 或 NULL:不產生 id 屬性
  • id > 0:產生 id="_N" (N 為數字)
  • id < 0:產生 id="idN"
  • 字串 id:直接作為 id 值

這使得同一物件可被多處引用,避免重複序列化:

// 共享同一字串物件
char *shared = "common";
soap_serialize_string(soap, &shared);
soap_out_string(soap, "str", 1, &shared, NULL);  // id="_1"
soap_out_string(soap, "str", 1, &shared, NULL);  // 同 id,第二次會輸出 

總結

  • 簡單單值輸出 → soap_put_TYPE (省事)
  • 陣列、重複、需引用、精確控制 XML 結構 → soap_out_TYPE + 手動 id
  • 結構體/字串/陣列 → **必先 soap_serialize_TYPE**
  • 記住 soap_destroy/end/free 三部曲

掌握這兩組 API 的分工,即能靈活產出符合規格的 SOAP XML,無論是 Web Service 回應、配置檔匯出、或裝置通訊協定實作都能得心應手。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved