iOS开发-进阶:使用SOAP访问Web服务

来源:互联网 发布:大学生网络借贷 编辑:程序博客网 时间:2024/05/29 04:16

SOAP是简单对象访问协议,它可看成是HTTP与XML的结合,其中XML部分是作为HTTP报文的实体主体部分。具体信息可以参考百度百科。

在iOS中使用SOAP,需要我们自己组装XML格式的字符串,当XML字符串比较长的时候会变得很麻烦。另外,我们在写XML格式的字符串时也要经常使用转义字符“\”。

为了编写我们的SOAP应用程序,先要找一个提供SOAP服务的网站,这里用的是http://www.webxml.com.cn,这是一个国内的提供Web服务的网站,很有意思。我们用到的是提供手机归属地查询的服务,具体网站是http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo。用浏览器打开这个网站,如下图:

若在mobileCode输入手机号码,userID不输入,点击调用,则结果如下:

这个结果呢不大准确,因为我输入的号码是动感地带的。但不影响本文主题。

看看刚才那个网页的内容,注意到SOAP 1.2标签下的内容:

POST /WebServices/MobileCodeWS.asmx HTTP/1.1Host: webservice.webxml.com.cnContent-Type: application/soap+xml; charset=utf-8Content-Length: length<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">  <soap12:Body>    <getMobileCodeInfo xmlns="http://WebXml.com.cn/">      <mobileCode>string</mobileCode>      <userID>string</userID>    </getMobileCodeInfo>  </soap12:Body></soap12:Envelope>

上面的这段文本就是使用SOAP 1.2的请求报文格式,就是一个HTTP请求报文,注意空行上面的那些内容中的请求行与各首部行的每个字段名,在下面的示例中会用到。这个HTTP请求报文的实体主体部分是XML格式的一段文本,注意Body标签之间的内容。

服务器的响应报文格式如下:

HTTP/1.1 200 OKContent-Type: application/soap+xml; charset=utf-8Content-Length: length<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">  <soap12:Body>    <getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/">      <getMobileCodeInfoResult>string</getMobileCodeInfoResult>    </getMobileCodeInfoResponse>  </soap12:Body></soap12:Envelope>

我们要用到的只有getMobileCodeInfoResult这个标签。

这次的例子是实现通过SOAP服务查询手机号码归属地、运行商等信息。PS:用的Xcode 4.4.1。

1、运行Xcode 4.4.1,新建一个Single View Application,名称为SOAP Test:

2、界面设计:打开ViewController.xib,设计界面如下所示:

在文本输入框的Attribute Inspector中设置其Keyboard属性为Number Pad。

3、之后向ViewController.h中,为文本输入框创建OutLet映射,名称为:phoneNumber;为“查询”按钮创建Action映射,事件类型为Touch Up Inside,名称为:doQuery。建立映射的方法就是打开Assistant Editor,选中某一控件,按住Ctrl,拖向ViewController.h,可以参考前面的文章。

4、在ViewController.h中添加代码:

4.1 在@interface那行最后添加代码

<NSXMLParserDelegate,  NSURLConnectionDelegate>

使ViewController遵守这两个协议。前者用来解析XML,后者用于网络连接。

4.2 在@end之前添加代码

@property (strong, nonatomic) NSMutableData *webData;@property (strong, nonatomic) NSMutableString *soapResults;@property (strong, nonatomic) NSXMLParser *xmlParser;@property (nonatomic) BOOL elementFound;@property (strong, nonatomic) NSString *matchingElement;@property (strong, nonatomic) NSURLConnection *conn;

5、在ViewController.m中添加代码:

5.1 在@implementation之后添加代码

@synthesize webData;@synthesize soapResults;@synthesize xmlParser;@synthesize elementFound;@synthesize matchingElement;@synthesize conn;

5.2 实现doQuery方法

// 开始查询- (IBAction)doQuery:(id)sender {    NSString *number = phoneNumber.text;        // 设置我们之后解析XML时用的关键字,与响应报文中Body标签之间的getMobileCodeInfoResult标签对应    matchingElement = @"getMobileCodeInfoResult";    // 创建SOAP消息,内容格式就是网站上提示的请求报文的实体主体部分    NSString *soapMsg = [NSString stringWithFormat:                         @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"                         "<soap12:Envelope "                         "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "                         "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "                         "xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">"                         "<soap12:Body>"                         "<getMobileCodeInfo xmlns=\"http://WebXml.com.cn/\">"                         "<mobileCode>%@</mobileCode>"                         "<userID>%@</userID>"                         "</getMobileCodeInfo>"                         "</soap12:Body>"                         "</soap12:Envelope>", number, @""];        // 将这个XML字符串打印出来    NSLog(@"%@", soapMsg);    // 创建URL,内容是前面的请求报文报文中第二行主机地址加上第一行URL字段    NSURL *url = [NSURL URLWithString: @"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"];    // 根据上面的URL创建一个请求    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];    NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMsg length]];    // 添加请求的详细信息,与请求报文前半部分的各字段对应    [req addValue:@"application/soap+xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];    [req addValue:msgLength forHTTPHeaderField:@"Content-Length"];    // 设置请求行方法为POST,与请求报文第一行对应    [req setHTTPMethod:@"POST"];    // 将SOAP消息加到请求中    [req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];    // 创建连接    conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];    if (conn) {        webData = [NSMutableData data];    }}

5.3 在@end之前添加代码

#pragma mark -#pragma mark URL Connection Data Delegate Methods// 刚开始接受响应时调用-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *) response{    [webData setLength: 0];}// 每接收到一部分数据就追加到webData中-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *) data {    [webData appendData:data];}// 出现错误时-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *) error {    conn = nil;    webData = nil;}// 完成接收数据时调用-(void) connectionDidFinishLoading:(NSURLConnection *) connection {    NSString *theXML = [[NSString alloc] initWithBytes:[webData mutableBytes]                                                length:[webData length]                                              encoding:NSUTF8StringEncoding];        // 打印出得到的XML    NSLog(@"%@", theXML);    // 使用NSXMLParser解析出我们想要的结果    xmlParser = [[NSXMLParser alloc] initWithData: webData];    [xmlParser setDelegate: self];    [xmlParser setShouldResolveExternalEntities: YES];    [xmlParser parse];}

5.4 在@end之前添加代码

#pragma mark -#pragma mark XML Parser Delegate Methods// 开始解析一个元素名-(void) parser:(NSXMLParser *) parser didStartElement:(NSString *) elementName namespaceURI:(NSString *) namespaceURI qualifiedName:(NSString *) qName attributes:(NSDictionary *) attributeDict {    if ([elementName isEqualToString:matchingElement]) {        if (!soapResults) {            soapResults = [[NSMutableString alloc] init];        }        elementFound = YES;    }}// 追加找到的元素值,一个元素值可能要分几次追加-(void)parser:(NSXMLParser *) parser foundCharacters:(NSString *)string {    if (elementFound) {        [soapResults appendString: string];    }}// 结束解析这个元素名-(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {    if ([elementName isEqualToString:matchingElement]) {        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"手机号码信息"                                                        message:[NSString stringWithFormat:@"%@", soapResults]                                                       delegate:self                                              cancelButtonTitle:@"确定"                                              otherButtonTitles:nil];        [alert show];        elementFound = FALSE;        // 强制放弃解析        [xmlParser abortParsing];    }}// 解析整个文件结束后- (void)parserDidEndDocument:(NSXMLParser *)parser {    if (soapResults) {        soapResults = nil;    }}// 出错时,例如强制结束解析- (void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {    if (soapResults) {        soapResults = nil;    }}

6、运行

  

其中,输入号码时单击查询,打印出的响应XML如下:

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">    <soap:Body>        <getMobileCodeInfoResponse xmlns="http://WebXml.com.cn/">            <getMobileCodeInfoResult>151898XXXXX:江苏 南京 江苏移动全球通卡            </getMobileCodeInfoResult>        </getMobileCodeInfoResponse>    </soap:Body></soap:Envelope>

上面的XML进行了缩进处理,实际上打印出来的是一行。

完整代码:http://www.oschina.net/code/snippet_164134_13248

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 行车记录仪内存卡丢了怎么办 投资项目失败lp的钱怎么办 无线网无ip分配怎么办 为什么电脑的暴风影音打不开怎么办 电枪充电板进水怎么办 捡到一颗子弹该怎么办 防弹衣只保护身体那手臂怎么办? 被子被宝宝尿湿怎么办 眼睛被子弹打了怎么办 gta5买了2套衣服怎么办 gta5车被摧毁了怎么办 gta5车被损坏了怎么办 头盔玻璃磨花了怎么办 浇花喷水壶坏了怎么办 电力专用光缆撞了怎么办 国防电缆挖断了怎么办 国防光缆挖断了怎么办 房门前乱挂光纤线影响住户怎么办 挂断低于限高的光缆怎么办 开大车挂住光缆怎么办 风把树枝挂断压到车该怎么办 货车柴油冻住了怎么办 尖头鞋老是折尖怎么办 打 氟氯西林疼怎么办 多余的十字绣线怎么办 硅胶类的东西沾到蓝药水怎么办? ph计斜率不到90怎么办 ph计斜率低于90怎么办 顾客说衣服起球怎么办 买的手机壳太滑怎么办 硅胶手机壳太滑怎么办 磨砂手机壳太滑怎么办 被热胶棒烫了怎么办 车钢垫子次了怎么办 【图】机组主轴密封漏水怎么办? 孕妇吃了好多杏怎么办 怀孕6个月吃了好多杏怎么办 白色纯棉衣服染色了怎么办 红色硅胶壳黑了怎么办 小米6gps信号弱怎么办 网线头卡子断了怎么办