reading complex soap response, having IDs and IDREFs nodes with Sudzc [iOS]

376 views Asked by At

I have problem with parsing soap response using Sudzc (ARC branch). I have some WCF service which stores data for our apps. I managed to connect to web service I can get response successfully, however I got stuck when one of responses came with z:ref attribute. It is hard to explain without an example right ? ;) /i have replaced important data with for example "#someid" so do not point that it is a problem ;)

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
    <ActivityId>#some credentials </ActivityId>
</s:Header>
<s:Body>
    <GetMessagesResponse >
        <GetMessagesResult  xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <AllItemsCount>2</AllItemsCount>
            <Items>
                <Message z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
                    <GlobalId>#msgid</GlobalId>
                    <Content>bbbbbbbb</Content>
                    <CreatedDate>2013-02-14T16:33:07</CreatedDate>
                    <Priority>Normal</Priority>
                    <Receiver z:Id="i2">
                        <GlobalId>#receiverid</GlobalId>
                        <CountryId>37</CountryId>
                        <CreationDate>2013-01-31T16:12:40</CreationDate>
                        <Gender>Male</Gender>
                        <IsDeleted>false</IsDeleted>
                        <Picture i:nil="true" />
                        <UserName>tobiasz</UserName>
                    </Receiver>
                    <Sender z:Id="i3">
                        <GlobalId>#senderid</GlobalId>
                        <CountryId>6</CountryId>
                        <CreationDate>2013-02-04T13:08:40</CreationDate>
                        <Gender>Male</Gender>
                        <IsDeleted>false</IsDeleted>
                        <Picture >
                            #"picture info"
                        </Picture>
                        <UserName>tobiasz2</UserName>
                    </Sender>
                    <Topic>RE: 56765765</Topic>
                </Message>
                <Message z:Id="i4" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
                    <GlobalId>#msgid2</GlobalId>
                    <Content>aaaaaaa</Content>
                    <CreatedDate>2013-02-14T16:31:01</CreatedDate>
                    <Priority>High</Priority>
                    <Receiver z:Ref="i2"/>
                    <Sender z:Ref="i3"/>
                    <Topic>RE: 56765765</Topic>
                </Message>
            </Items>
            <PageIndex>0</PageIndex>
            <RetrievedDateTime>2013-02-15T13:14:57.0813487Z</RetrievedDateTime>
        </GetMessagesResult>
    </GetMessagesResponse>
</s:Body>

As You can see there are lines which identifies Receiver node as i2 and further You can see node of another message from the same sender and to the same receiver

sudzc generated class used to parse this xml:

@interface ResultOfGetMessages : SoapObject{
    int _AllItemsCount;
    NSMutableArray* _Items;
    int _PageIndex;
    NSDate* _RetrievedDateTime;
}

@interface Message : WSGlobalObject{
    NSString* _Content;
    NSDate* _CreatedDate;
    NSString* _Priority;
    User* _Receiver;
    User* _Sender;
    NSString* _Topic;
}

@interface User : WSGlobalObject{
    int _CountryId;
    NSDate* _CreationDate;
    NSString* _Gender;
    BOOL _IsDeleted;
    PictureInfo* _Picture;
    NSString* _UserName;
}

Sudz with Touchxml fails to read that (getting null receiver and sender), response is parsed as:

<ResultOfGetMessages>
<AllItemsCount>2</AllItemsCount>
<Items>
    <Message>
        <GlobalId>###</GlobalId>
        <Content>bbbbbbbb</Content>
        <CreatedDate>2013-02-14T16:33:07.000</CreatedDate>
        <Priority>Normal</Priority>
        <Receiver>
            <GlobalId>####</GlobalId>
            <CountryId>37</CountryId>
            <CreationDate>2013-01-31T16:12:40.000</CreationDate>
            <Gender>Male</Gender>
            <IsDeleted>false</IsDeleted>
            <Picture i:nil="true" ></Picture>
            <UserName>tobiasz</UserName>
            <Version>11</Version>
        </Receiver>
        <Sender>
            <GlobalId>e4bda93c-a11c-4ae2-baf1-a15b00e918e7</GlobalId>
            <CountryId>6</CountryId>
            <CreationDate>2013-02-04T13:08:40.000</CreationDate>
            <Gender>Male</Gender>
            <IsDeleted>false</IsDeleted>
            <Picture >
                ####
            </Picture>
            <UserName>tobiasz2</UserName>
            <Version>11</Version>
        </Sender>
        <Topic>RE: 56765765</Topic>
    </Message>
    <Message>
        <GlobalId>###</GlobalId>
        <Content>aaaaaaa</Content>
        <CreatedDate>2013-02-14T16:31:01.000</CreatedDate>
        <Priority>High</Priority>
        <Receiver>
            <CountryId>0</CountryId>
            <IsDeleted>false</IsDeleted>
        </Receiver>
        <Sender>
            <CountryId>0</CountryId>
            <IsDeleted>false</IsDeleted>
        </Sender>
        <Topic>RE: 56765765</Topic>
    </Message>
</Items>
<PageIndex>0</PageIndex>

I think problems lays in depth of deserialization. Parser (if) tries to get the receiver node with specified id however it fails because receiver node marked with this id is in other node (previous item node).

Thanks in advance for help and your time.

1

There are 1 answers

1
iDev On

I had a simular problem with the soap.m when it serialized the nodes. had to this code:

// Deserializes the element in a dictionary.
+(id)deserializeAsDictionary:(CXMLNode*)element {

if([element childCount] == 1) {
CXMLNode* child = [[element children] objectAtIndex:0];
if([child kind] == CXMLTextKind) 
{
     NSLog(@"The Child Node: %@", [[[element children] objectAtIndex:0] stringValue]);
    return [[[element children] objectAtIndex:0] stringValue];

}
}

NSMutableDictionary* d = [NSMutableDictionary dictionary];
for(CXMLNode* child in [element children]) {
id v = [Soap deserialize:child];
if(v == nil) { v = [NSNull null]; }
[d setObject:v forKey:[child name]];
}
return d;
}

to:

// Deserializes the element in a dictionary.
+(id)deserializeAsDictionary:(CXMLNode*)element {

if([element childCount] == 1) {
CXMLNode* child = [[element children] objectAtIndex:0];
if([child kind] == CXMLTextKind) 
{
     NSLog(@"The Child Node: %@", [[[element children] objectAtIndex:0] stringValue]);
    return [[[element children] objectAtIndex:0] stringValue];

}
}

NSMutableDictionary* d = [NSMutableDictionary dictionary];
for(CXMLNode* child in [element children]) {
id v = [Soap deserialize:child];
if(v == nil) { v = [NSNull null]; }
[d setObject:v forKey:[child name]];

if( check != nil ) {             
NSInteger next = 1;             
key = [NSString stringWithFormat:@"%@%04d", [child name], next];
check = [d objectForKey:key]; 
while( check != nil ) {                 
    next++; 
    key = [NSString stringWithFormat:@"%@%04d", [child name], next]; 
    check = [d objectForKey:key]; 
} 
[d setObject:v forKey:key]; 
} else {
[d setObject:v forKey:[child name]];
}