【问题标题】:Need to extract XML document from NSMutableData object in iOS需要从 iOS 中的 NSMutableData 对象中提取 XML 文档
【发布时间】:2013-05-01 15:00:52
【问题描述】:

我已成功从 iOS 连接到 .NET Web 服务,并通过 NSLog 将响应 xml 文档打印到控制台。这是我通过 AFNetworking 库进行的。我现在可以通过 NSURLConnection 连接到同一个 Web 服务,但是,我无法提取保存在 NSMutableData 对象中的 xml 文档。 AFNetworking 库能够自动执行此操作,这使事情变得更加容易,但我想知道如何使用本机 iOS 库来执行此操作。这是我正在使用的代码:

//This is the code I am using to make the connection to the web service
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    [request setHTTPBody:[soapBody dataUsingEncoding:NSUTF8StringEncoding]];

    [request setHTTPMethod:@"POST"];

    [request addValue:@"http://tempuri.org/Customers" forHTTPHeaderField:@"SOAPAction"];
    [request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

    // Convert your data and set your request's HTTPBody property
    NSString *stringData = @"some data";
    NSData *requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody = requestBodyData;

    // Create url connection and fire request
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    [conn start];

这是我必须从网络服务接收数据的代码:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    _responseData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {

    [_responseData appendData:data];
}

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse*)cachedResponse {
    return nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    // The request is complete and data has been received
    NSString *strData = [[NSString alloc]initWithData:_responseData encoding:NSUTF8StringEncoding];

    NSLog(@"%@", strData);

}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    // The request has failed for some reason!

}


/*
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        NSLog(@"%@", [operation responseString]);

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        NSLog(@"failed");

    }];

    [operation start];
    */

我只是想打印出我收到的整个 xml 文档,而现在不一定要解析该文档。

提前感谢所有回复的人。

【问题讨论】:

  • 那么这段代码会发生什么?你能走多远?它是否完成加载? strData 的日志输出是什么?如果没有完成,请在didFailWithError 方法中添加错误日志。
  • 很抱歉。不幸的是,当我执行 NSLog(strData); 时,控制台没有输出。但是,如果我这样做 NSLog(_responseData);我得到 出现在我的控制台中。我希望这会有所帮助。
  • 这意味着响应正在完成,但您没有得到任何数据。您是否通过调试器运行您的应用程序并在所有NSURLConnection 委托方法上设置断点?查看正在调用的内容并查看未调用的内容。你对服务器有控制权吗?如果是这样,请查看它收到了什么请求以及它正在发送什么响应。将其与您在 iOS 应用中获得的内容进行比较。
  • 小观察:你不需要start你的NSURLConnection。如果您将initWithRequest:delegate:startImmediately:NO 一起用于startImmediately,您只需要这样做。另外,_responseData 是如何定义的?如果weak,则不会为您保留。此外,如果这是 responseData 属性的后备 ivar,您通常应该 use accessor methods when to set property values
  • @Rob:感谢您指出这一点。 _responseData 在头文件中被定义为(非原子,保留)属性。

标签: ios nsurlconnection nsmutableurlrequest nsmutabledata


【解决方案1】:

查看您服务器上的帮助文档,它提出了一个示例请求:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <Customers xmlns="http://tempuri.org/" />
  </soap:Body>
</soap:Envelope>

所以,我将该示例请求放在一个文本文件中,并通过NSURLConnection 发起请求,如下所示:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

NSString *filename = [[NSBundle mainBundle] pathForResource:@"soap1-1example" ofType:@"xml"];
NSData *requestBodyData = [NSData dataWithContentsOfFile:filename];
request.HTTPBody = requestBodyData;

[request setHTTPMethod:@"POST"];

[request addValue:@"http://tempuri.org/Customers" forHTTPHeaderField:@"SOAPAction"];
[request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

[NSURLConnection connectionWithRequest:request delegate:self];

注意,我没有调用start,因为as the documentation says 除非您使用“initWithRequest:delegate:startImmediately: 方法并为startImmediately 参数提供NO”,否则它将自动为您启动。实际上,您的原始代码启动了两次连接,这可能有问题。

无论如何,使用我修改后的代码和上述请求,它工作正常,同时使用NSURLConnection 以及AFNetworking。我得到的回应(美化)是:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
    <CustomersResponse xmlns="http://tempuri.org/">
    <CustomersResult>
        <Customer>
            <FirstName>Mohammad</FirstName>
            <LastName>Azam</LastName>
        </Customer>
        <Customer>
            <FirstName>John</FirstName>
            <LastName>Doe</LastName>
        </Customer>
    </CustomersResult>
</CustomersResponse>
</soap:Body>
</soap:Envelope>

如果它仍然不适合您,也许您可​​以分享您提交的请求的详细信息。


顺便说一句,由于这里不需要委托方法(例如,您没有进行流式传输,您没有进行任何身份验证等),因此您可以消除所有 NSURLConnectionDataDelegate 方法(didReceiveResponsedidReceiveData 等),只需使用NSURLConnection 类方法,sendAsynchronousRequest(在 iOS 5 及更高版本中):

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

NSString *filename = [[NSBundle mainBundle] pathForResource:@"soap1-1example" ofType:@"xml"];
NSData *requestBodyData = [NSData dataWithContentsOfFile:filename];
NSAssert(requestBodyData, @"requestBodyData is nil!");
request.HTTPBody = requestBodyData;

[request setHTTPMethod:@"POST"];

[request addValue:@"http://tempuri.org/Customers" forHTTPHeaderField:@"SOAPAction"];
[request addValue:@"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];

if (!self.networkQueue)
{
    self.networkQueue = [[NSOperationQueue alloc] init];
    self.networkQueue.name = @"com.yourdomain.yourapp.networkQueue";
}

[NSURLConnection sendAsynchronousRequest:request
                                   queue:self.networkQueue
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

                           if (!error)
                           {
                               NSString *string = [[NSString alloc] initWithData:data
                                                                        encoding:NSUTF8StringEncoding];

                               NSLog(@"%s: data=%@", __FUNCTION__, string);
                           }
                           else
                           {
                               NSLog(@"%s: error=%@", __FUNCTION__, error);
                           }
                       }];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-30
    • 2015-05-10
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多