SudzC显示'有效'肥皂响应,但在iOS方面为空值

时间:2012-03-30 22:11:55

标签: objective-c ios web-services soap

我是SOAP和iOS的新手,所以请耐心等待。 我正在尝试使用生成的源SudzC来使用SOAP WS。

看看输出,事情看起来几乎正常。我可以看到我需要的数据,因此数据似乎正在跨越线路:

2012-03-30 17:26:14.131 EZSystem[892:707] 
Loading: http://xx.xx.xx.xxx:xxxx/service

2012-03-30 17:26:14.137 EZSystem[892:707]
<?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/" 
    xmlns="http://database.usah.com/">
<soap:Body>
    <getQB2012CustomerDictionaryXML></getQB2012CustomerDictionaryXML>
</soap:Body>
</soap:Envelope>

2012-03-30 17:26:14.485 EZSystem[892:707] 
<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:getQB2012CustomerDictionaryXMLResponse
    xmlns:ns2="http://xxxxxx/">
    <return>
        &lt;?xml version="1.0" encoding="UTF-8" standalone="no"?&gt;&lt;!-- 
        &lt;[Quickbooks tag]&gt;Database Column Name&lt;/[Quickbooks tag]&gt;
        --&gt;&lt;CustomerRet database_root_tag="Customers" id="id_customers" 
        ...
        ...
        ...
    </return>
</ns2:getQB2012CustomerDictionaryXMLResponse>
</S:Body>
</S:Envelope>

我发送的是一个表示XML的字符串,或者是XML。

但是,以下代码返回null:

-(void)logIn{
    DictionaryQB2012DatabaseKeyService* service = 
        [DictionaryQB2012DatabaseKeyService service];

    service.logging = YES;

    // Returns NSString*. 
    [service getQB2012CustomerDictionaryXML:self 
        action:@selector(getQB2012CustomerDictionaryXMLHandler:)];
}

// Handle the response from getQB2012CustomerDictionaryXML.
- (void) getQB2012CustomerDictionaryXMLHandler: (id) value {

    // Handle errors
    if([value isKindOfClass:[NSError class]]) {
        NSLog(@"%@", value);
        return;
    }


    // Handle faults
    if([value isKindOfClass:[SoapFault class]]) {
        NSLog(@"%@", value);
        return;
    }

    // Do something with the NSString* result

    NSString* result = (NSString*)value;
    NSLog(@"getQB2012CustomerDictionaryXML returned the value: %@", result);

}

该值为空。

在这个过程中它崩溃了吗?似乎我收到了我需要的数据,但是将它转换为OBJ-C字符串失败了。

任何帮助将不胜感激,

戴恩

1 个答案:

答案 0 :(得分:1)

在SudzC中生成了SoapRequest.m:

- (void) connectionDidFinishLoading:(NSURLConnection *) connection {
    ...
    if(self.logging == YES){
       NSString* response = [[NSString alloc] initWithData: self.receivedData 
        encoding: NSUTF8StringEncoding];
       NSLog(@"%@", response);
    }    
    ...
}

响应是原始SOAP响应,它包含预期的数据。

用同样的方法,

CXMLNode* element = [[Soap getNode: [doc rootElement] withName: @"Body"] 
    childAtIndex:0];

此行从SOAP响应中获取返回值。经过一番探讨,事实证明“身体”是问题所在:

SOAP响应具有“S:Body”,因此将withName更改为正确的标记名称可以修复所有内容。

这让我感到困扰,因为我不知道我的WS是错还是什么,但我现在就把它拿走。

此外,可能必须修改Soap.m,因为它使用“soap”而不是“soapenv”。这些值是硬编码的,但变化相当容易。

此外,命名空间保留为空:

[s appendFormat:@"=\"http://schemas.xmlsoap.org/soap/envelope/\" 
xmlns=\"%@\">", ns]; 

这可能必须是xmlns:[namespace] = \“%@”... 其中namespace是剥离的命名空间。

那是:

http://namespace/ => namespace

此外,您无法接收字符串结果并在示例中使用它,至少在我的结尾。 例如:

NSString* result = (NSString*) value;

应该产生null。然而,这似乎有效:

NSDictionary* result = (NSDictionary*)value;
NSString* finalResult = [[result allValues] objectAtIndex:0];

如果有人有兴趣,这里是对我制作的Soap.m的修改。

// Soap.m

NSString* const SOAP_PREFIX = @"soapenv";
NSString* const HTTP_PREFIX = @"http://";
NSUInteger const FORWARD_FLASH_CHARACTER_VALUE = 47;

// Creates the XML request for the SOAP envelope with optional SOAP headers.
+ (NSString*) createEnvelope: (NSString*) method forNamespace: (NSString*) ns         
    forParameters: (NSString*) params withHeaders: (NSDictionary*) headers
    {
        NSMutableString* s = [NSMutableString string];

    [s appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
        [s appendString: @"<"];
        [s appendString: SOAP_PREFIX];
        [s appendString:@":Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-
            instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""];
        [s appendString:@" xmlns:"];
        [s appendString: SOAP_PREFIX];

        NSString* rawNamespace = [Soap getRawNamespace:ns];
        [s appendFormat:@"=\"http://schemas.xmlsoap.org/soap/envelope/\" 
            xmlns:%@=\"%@\">", rawNamespace, ns];

        if(headers != nil && headers.count > 0) {
            [s appendString: @"<"];
            [s appendString: SOAP_PREFIX];
            [s appendString:@":Header>"];

            for(id key in [headers allKeys]) {
        if([[headers objectForKey: key] isMemberOfClass: [SoapNil class]])     
                {
                [s appendFormat: @"<%@ xsi:nil=\"true\"/>", key];
        } else {
                [s appendString:[Soap serializeHeader:headers forKey:key]];
        }
        }  
            [s appendString: @"</"];
            [s appendString: SOAP_PREFIX];
            [s appendString:@":Header>"];
    }

    [s appendString: @"<"];
        [s appendString: SOAP_PREFIX];
        [s appendString:@":Body>"];

        NSMutableString* fullMethodName = [NSMutableString string];
        [fullMethodName appendString:rawNamespace];
        [fullMethodName appendString:@":"];
        [fullMethodName appendString:method];

    [s appendFormat: @"<%@>%@</%@>", fullMethodName,[params 
            stringByReplacingOccurrencesOfString:@"&" withString:@"&amp;"], 
            fullMethodName];


        [s appendString: @"</"];
        [s appendString: SOAP_PREFIX];
        [s appendString:@":Body>"];
        [s appendString: @"</"];
        [s appendString: SOAP_PREFIX];
        [s appendString:@":Envelope>"];
    return s;
}


+(NSString*)getRawNamespace:(NSString *)value{
    if([value hasPrefix:HTTP_PREFIX]){
        NSString* rawNamespace = [value substringFromIndex:([HTTP_PREFIX length])];

        if([rawNamespace length] == 0){
            return @"";
        }
        // strip out a trailing slash
        if([rawNamespace characterAtIndex:([rawNamespace length]- 1)] ==             
            FORWARD_FLASH_CHARACTER_VALUE){
            NSRange range = NSMakeRange (0, [rawNamespace length] - 1);
            rawNamespace = [rawNamespace substringWithRange:(range)];
        }
        return rawNamespace;           
    }
    else{
        return value;
    }
}