当前位置:首页 > 行业动态 > 正文

C中如何调用soap api

在C中调用SOAP API,需先创建SOAP请求,再发送请求并解析响应。这通常涉及使用第三方库如libcurl和libxml2来处理HTTP请求和XML解析。

在C语言中调用SOAP API通常需要借助第三方库来处理HTTP请求和XML解析,因为C语言本身并没有内置对SOAP协议的直接支持,以下是详细的步骤和示例代码,帮助你在C语言中调用SOAP API:

1、准备工作

安装必要的库:确保你的开发环境中安装了libcurl(用于HTTP请求)和libxml2(用于解析XML),在Ubuntu系统中,可以使用以下命令安装这些库:

 sudo apt-get install libcurl4-openssl-dev libxml2-dev

2、创建SOAP请求

SOAP请求是一个XML格式的字符串,包含了调用的Web服务方法和所需的参数,以下是一个调用名为GetWeather的方法的SOAP请求示例:

C中如何调用soap api

 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">
       <soapenv:Header/>
       <soapenv:Body>
         <web:GetWeather>
           <web:CityName>New York</web:CityName>
           <web:CountryName>United States</web:CountryName>
         </web:GetWeather>
       </soapenv:Body>
     </soapenv:Envelope>

在C语言中,你可以将这个XML字符串存储在一个字符数组中:

 const char *soapRequest =
         "<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">"
         "<soapenv:Header/>"
         "<soapenv:Body>"
         "<web:GetWeather>"
         "<web:CityName>New York</web:CityName>"
         "<web:CountryName>United States</web:CountryName>"
         "</web:GetWeather>"
         "</soapenv:Body>"
         "</soapenv:Envelope>";

3、发送SOAP请求

使用libcurl库发送HTTP请求,将SOAP请求发送到Web服务的URL,以下是一个使用libcurl发送HTTP POST请求的示例代码:

C中如何调用soap api

 #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include <curl/curl.h>
     const char *soapRequest =
         "<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">"
         "<soapenv:Header/>"
         "<soapenv:Body>"
         "<web:GetWeather>"
         "<web:CityName>New York</web:CityName>"
         "<web:CountryName>United States</web:CountryName>"
         "</web:GetWeather>"
         "</soapenv:Body>"
         "</soapenv:Envelope>";
     struct MemoryStruct {
       char *memory;
       size_t size;
     };
     static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
       size_t realsize = size * nmemb;
       struct MemoryStruct *mem = (struct MemoryStruct *)userp;
       char *ptr = realloc(mem->memory, mem->size + realsize + 1);
       if(ptr == NULL) {
         printf("not enough memory (realloc returned NULL)
");
         return 0;
       }
       mem->memory = ptr;
       memcpy(&(mem->memory[mem->size]), contents, realsize);
       mem->size += realsize;
       mem->memory[mem->size] = 0;
       return realsize;
     }
     int main(void) {
       CURL *curl;
       CURLcode res;
       struct MemoryStruct chunk;
       chunk.memory = malloc(1);  // 分配初始内存
       chunk.size = 0;  // 初始化大小为0
       curl_global_init(CURL_GLOBAL_ALL);  // 初始化libcurl
       curl = curl_easy_init();  // 初始化CURL对象
       if(curl) {
         curl_easy_setopt(curl, CURLOPT_URL, "http://www.webservicex.net/globalweather.asmx");  // 设置目标URL
         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, soapRequest);  // 设置POST数据为SOAP请求
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);  // 设置回调函数处理响应数据
         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);  // 设置回调函数的用户数据指针
         // 如果需要,可以添加额外的HTTP头,例如Content-Type
         struct curl_slist *headers = NULL;
         headers = curl_slist_append(headers, "Content-Type: text/xml; charset=utf-8");
         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);  // 设置HTTP头
         res = curl_easy_perform(curl);  // 执行请求
         if(res != CURLE_OK) {
           fprintf(stderr, "curl_easy_perform() failed: %s
", curl_easy_strerror(res));
         } else {
           printf("%lu bytes retrieved
", (unsigned long)chunk.size);
           printf("Response: %s
", chunk.memory);  // 打印响应数据
         }
         curl_slist_free_all(headers);  // 释放HTTP头列表
         curl_easy_cleanup(curl);  // 清理CURL对象
       }
       free(chunk.memory);  // 释放内存
       curl_global_cleanup();  // 清理libcurl全局数据
       return 0;
     }

上述代码中,首先定义了一个MemoryStruct结构体来存储响应数据,使用curl_easy_setopt函数设置了请求的URL、POST数据、回调函数等选项,通过curl_easy_perform函数发送请求并获取响应。

4、解析响应

接收到的响应是一个XML格式的字符串,需要将其解析成可用的C语言结构,这通常需要使用XML解析库,如libxml2,以下是一个使用libxml2解析XML响应的简单示例:

C中如何调用soap api

 #include <libxml/parser.h>
     #include <libxml/tree.h>
     #include <stdio.h>
     #include <string.h>
     void parseXmlResponse(const char *response) {
       xmlDocPtr doc;  // 定义文档指针
       xmlNode *root_element = NULL;
       // 解析XML文档
       doc = xmlReadMemory(response, strlen(response), "noname.xml", NULL, 0);
       if (doc == NULL) {
         fprintf(stderr, "Failed to parse document
");
         return;
       }
       // 获取根元素节点
       root_element = xmlDocGetRootElement(doc);
       for (xmlNode *node = root_element->children; node; node = node->next) {
         if (node->type == XML_ELEMENT_NODE && !xmlStrcmp(node->name, (const xmlChar *)"GetWeatherResult")) {
           xmlChar *weatherText = xmlNodeGetContent(node);
           printf("Weather: %s
", weatherText);
           xmlFree(weatherText);
         }
       }
       // 清理文档树
       xmlFreeDoc(doc);
       // 清理全局变量
       xmlCleanupParser();
     }

上述代码中,首先使用xmlReadMemory函数将响应字符串解析成一个XML文档对象,遍历文档的子节点,找到名为GetWeatherResult的元素节点,并获取其内容,释放文档对象和全局变量。

5、完整示例

将上述发送请求和解析响应的代码结合起来,就可以实现一个完整的在C语言中调用SOAP API的示例:

 #include <stdio.h>
     #include <stdlib.h>
     #include <string.h>
     #include <curl/curl.h>
     #include <libxml/parser.h>
     #include <libxml/tree.h>
     const char *soapRequest =
         "<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://www.webserviceX.NET">"
         "<soapenv:Header/>"
         "<soapenv:Body>"
         "<web:GetWeather>"
         "<web:CityName>New York</web:CityName>"
         "<web:CountryName>United States</web:CountryName>"
         "</web:GetWeather>"
         "</soapenv:Body>"
         "</soapenv:Envelope>";
     struct MemoryStruct {
       char *memory;
       size_t size;
     };
     static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
       size_t realsize = size * nmemb;
       struct MemoryStruct *mem = (struct MemoryStruct *)userp;
       char *ptr = realloc(mem->memory, mem->size + realsize + 1);
       if(ptr == NULL) {
         printf("not enough memory (realloc returned NULL)
");
         return 0;
       }
       mem->memory = ptr;
       memcpy(&(mem->memory[mem->size]), contents, realsize);
       mem->size += realsize;
       mem->memory[mem->size] = 0;
       return realsize;
     }
     void parseXmlResponse(const char *response) {
       xmlDocPtr doc;  // 定义文档指针
       xmlNode *root_element = NULL;
       // 解析XML文档
       doc = xmlReadMemory(response, strlen(response), "noname.xml", NULL, 0);
       if (doc == NULL) {
         fprintf(stderr, "Failed to parse document
");
         return;
       }
       // 获取根元素节点
       root_element = xmlDocGetRootElement(doc);
       for (xmlNode *node = root_element->children; node; node = node->next) {
         if (node->type == XML_ELEMENT_NODE && !xmlStrcmp(node->name, (const xmlChar *)"GetWeatherResult")) {
           xmlChar *weatherText = xmlNodeGetContent(node);
           printf("Weather: %s
", weatherText);
           xmlFree(weatherText);
         }
       }
       // 清理文档树
       xmlFreeDoc(doc);
       // 清理全局变量
       xmlCleanupParser();
     }
     int main(void) {
       CURL *curl;
       CURLcode res;
       struct MemoryStruct chunk;
       chunk.memory = malloc(1);  // 分配初始内存
       chunk.size = 0;  // 初始化大小为0
       curl_global_init(CURL_GLOBAL_ALL);  // 初始化libcurl
       curl = curl_easy_init();  // 初始化CURL对象
       if(curl) {
         curl_easy_setopt(curl, CURLOPT_URL, "http://www.webservicex.net/globalweather.asmx");  // 设置目标URL
         curl_easy_setopt(curl, CURLOPT_POSTFIELDS, soapRequest);  // 设置POST数据为SOAP请求
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);  // 设置回调函数处理响应数据
         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);  // 设置回调函数的用户数据指针
         // 如果需要,可以添加额外的HTTP头,例如Content-Type
         struct curl_slist *headers = NULL;
         headers = curl_slist_append(headers, "Content-Type: text/xml; charset=utf-8");
         curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);  // 设置HTTP头
         res = curl_easy_perform(curl);  // 执行请求
         if(res != CURLE_OK) {
           fprintf(stderr, "curl_easy_perform() failed: %s
", curl_easy_strerror(res));
         } else {
           printf("%lu bytes retrieved
", (unsigned long)chunk.size);
           parseXmlResponse(chunk.memory);  // 解析响应数据
         }
         curl_slist_free_all(headers);  // 释放HTTP头列表
         curl_easy_cleanup(curl);  // 清理CURL对象
       }
       free(chunk.memory);  // 释放内存
       curl_global_cleanup();  // 清理libcurl全局数据
       return 0;
     }