0

我正在尝试使用 RestKit 解析 SOAP 响应。如果我自己定义映射和关系,我就能够成功地将 SOAP XML 响应转换为对象。但是,我想知道是否可以使用自省(或其他方法)将 SOAP XML 响应自动转换为 Objective-C 对象。

示例 XML:

<return>
    <userId xsi:type="xsd:int">1113050187</userId>
    <location xsi:type="ns1:Location">
       <city xsi:type="xsd:string">San Francisco</city>
       <state xsi:type="xsd:string">California</state>
    </location>
</return>

我想将此 XML 转换为此对象:

@interface Return : NSObject

@property (strong, nonatomic) NSInteger userId; // attribute
@property (strong, nonatomic) Location *location; // relation

@end

我能想到的最接近的事情是在 Return 类上使用自省来获取所有属性,并对每个属性使用类似的东西:[mapping addAttributeMapping:[RKObjectAttributeMapping mappingFromKeyPath:@"userId.text" toKeyPath:@"userId"]] ;

对于关系,我可以再次使用自省来找出我所有的类对象并在每个对象上使用 mapRelationship:withMapping:

4

1 回答 1

0

我最终定义了一个方法,如果它们的名称匹配,则递归地将属性映射到 XML 节点。命名约定和属性的数据类型对此很重要。

在将其发布到此处之前,我已尽力清理此内容,但如果您需要任何帮助,请告诉我。

- (RKObjectMapping *)mapMe:(Class)class
{
    RKObjectManager *objectManager = [RKObjectManager sharedManager];
    RKObjectMapping *mapping = [RKObjectMapping mappingForClass:class];
    id classType = objc_getClass([NSStringFromClass(class) UTF8String]);
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(classType, &outCount);
    for (i = 0; i < outCount; i++) {
        objc_property_t property = properties[i];
//        fprintf(stdout, "%s\n", property_getName(property));

        const char *type = property_getAttributes(property);
        NSString *typeString = [NSString stringWithUTF8String:type];
        NSArray *attributes = [typeString componentsSeparatedByString:@","];
//        NSLog(@"attributes = %@", attributes);
        NSString *typeAttribute = [attributes objectAtIndex:0];
//        NSLog(@"typeAttribute = %@", typeAttribute);
        NSString *propertyType = [typeAttribute substringFromIndex:1];

        if ([propertyType hasPrefix:@"@"] && [propertyType length] > 1) {
            NSString * typeClassName = [propertyType substringWithRange:NSMakeRange(2, [propertyType length]-3)];  //turns @"NSDate" into NSDate
            Class typeClass = NSClassFromString(typeClassName);
            if (typeClass != nil && ![typeClassName hasPrefix:@"NS"]) {
//            my custom class detected.
                RKObjectMapping *subMapping = [self mapMe:typeClass forObjectManager:objectManager];
                [mapping mapRelationship:[NSString stringWithUTF8String:property_getName(property)] withMapping:subMapping];
                [objectManager.mappingProvider setMapping:subMapping forKeyPath:[NSString stringWithUTF8String:property_getName(property)]];
            } else {
                [mapping addAttributeMapping:[RKObjectAttributeMapping mappingFromKeyPath:[NSString stringWithFormat:@"%@.text", [NSString stringWithUTF8String:property_getName(property)]] toKeyPath:[NSString stringWithUTF8String:property_getName(property)]]];
            }
        }
    }
    free(properties);
    return mapping;
}

然后映射它自动调用它:

[self mapMe:[Myclass class]];
于 2012-07-12T00:41:42.427 回答