Search code examples
objective-czend-frameworksoapnsmutablearraysudzc

How to access array fields in sudzc.com SOAP result?


Sorry to perhaps ask stupid questions, but I'm still having issues with Objective-C syntax. So, I've got this SOAP response from my sudzc.com generated code. It should contain a SQL SELECT result with veh_id and version as columns.

What I get as a response object is a NSMutableArray,

NSMutableArray* soapArray = (NSMutableArray*)value;

so I walk through it:

unsigned count = [soapArray count];
while (count--) {
   id myobj = [soapArray objectAtIndex:count];
   NSLog(@"myobj: %@", myobj); 
}

What I get as a printout is something like:

myobj: {
item =     {
    key = version;
    value = 1;
};

for each row of the SQL result. If this is a printout of the array element, why is there only the version column and not also the veh_id column?

How do I access the value for the key on the object myobj of type id? Do I have to cast it first?

That's the XML String returned from the Zend Soap-Server:

<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.[myurl].com/soap" xmlns:ns2="http://xml.apache.org/xml-soap" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:getActiveVehiclesResponse><return SOAP-ENC:arrayType="ns2:Map[23]" xsi:type="SOAP-ENC:Array"><item xsi:type="ns2:Map"><item><key xsi:type="xsd:string">veh_id</key><value xsi:type="xsd:string">1</value></item><item><key xsi:type="xsd:string">version</key><value xsi:type="xsd:string">1</value></item></item><item xsi:type="ns2:Map"><item><key xsi:type="xsd:string">veh_id</key><value xsi:type="xsd:string">3</value></item><item><key xsi:type="xsd:string">version</key><value xsi:type="xsd:string">1</value></item></item><item xsi:type="ns2:Map"><item><key xsi:type="xsd:string">veh_id</key><value xsi:type="xsd:string">4</value></item><item><key xsi:type="xsd:string">version</key><value xsi:type="xsd:string">1</value></item></item></return></ns1:getActiveVehiclesResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>

Solution

  • Finally found the solution! The problem lies within the deserializeAsDictionary function. Since my Soap xml string is structured to have each database column as item - key - value - key - value etc, it adds each column under the key "item" and thus the deserializeAsDictionary function overwrites in the line

    [d setObject:v forKey:[child name]]
    

    the already added objects. In a first shot, I have added a column iterator and now call the columns "item1, item2,.." (further optimization might be necessary):

    // Deserializes the element in a dictionary.
    +(id)deserializeAsDictionary:(CXMLNode*)element {
    NSLog(@"deserializeAsDictionary = %@, children: %d", element.stringValue, [element childCount]);
    
    if([element childCount] == 1) {
        CXMLNode* child = [[element children] objectAtIndex:0];
        if([child kind] == CXMLTextKind) {
           NSLog(@"child %@ added", [child stringValue]);
            return [[[element children] objectAtIndex:0] stringValue];
        }
    }
    
    NSMutableDictionary* d = [NSMutableDictionary dictionary];
    NSInteger i = 1;
    NSString *objKey;
    for(CXMLNode* child in [element children]) {
        id v = [Soap deserialize:child];
        if(v == nil) { 
            v = [NSNull null]; 
        } else {
            if([[child name] isEqualToString:@"(null)"]) {
                objKey = [NSString stringWithFormat:@"%@",[child stringValue]];
            } else if([[child name] isEqualToString:@"key"] || [[child name] isEqualToString:@"value"]) { 
                objKey = [NSString stringWithFormat:@"%@",[child name]];
            } else {
                objKey = [NSString stringWithFormat:@"%@%d",[child name],i++];
            }
    
        }
    
        [d setObject:v forKey:objKey];
        NSLog(@"child %@ added", objKey);
    }
    return d;
    } 
    

    The result array now looks like:

    },
        {
        item1 =         {
            key = "veh_id";
            value = 29;
        };
        item2 =         {
            key = version;
            value = 1;
        };
    }