Question

I am trying to parse xml using the touchXML library but not getting the results, the code is as below

NSError *error = nil;    
CXMLDocument *xmlParser = [[CXMLDocument alloc] initWithXMLString:dataString options:0 error:&error];

NSArray *resultNodes = NULL;
resultNodes = [xmlParser nodesForXPath:@"//entry" error:&error];

for (CXMLElement *resultElement in resultNodes) {
    NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];

    int counter;

    for(counter = 0; counter < [resultElement childCount]; counter++) {
        [blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
    }        
} 

the method nodesForXPath: doesn't returns anything leaving the resultNodes array with 0 objects. I am getting the proper xml in dataString and the CXMLDocument is also getting prepared properly. I tried debugging it but there is nothing I can see accept the 0 objects in resultNodes, NSError also contains nothing (i.e. no error occurs). the xml file I am trying to parse is as below.

<feed xmlns:s="http://syndication.nhschoices.nhs.uk/services" xmlns="http://www.w3.org/2005/Atom">
<title type="text">...</title>
<id>...</id>
<rights type="text">© Crown Copyright 2009</rights>
<updated>2012-04-27T11:33:02+01:00</updated>
<category term="Search"/>
<logo>...</logo>
<author>...</author>
<s:SearchCoords>174900,517900</s:SearchCoords>
<entry>
    <id>
        http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/32248
    </id>
    <title type="text">Sayer A</title>
    <updated>2012-04-27T10:33:02Z</updated>
    <link rel="self" title="Sayer A" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/32248?apikey=YAHUGHET"/>
    <link rel="alternate" title="Sayer A" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=15F37AEF-EC5B-4A90-9E72-269ADEB39629"/>
    <content type="application/xml">
        <s:organisationSummary>
            <s:name>Sayer A</s:name>
            <s:address>
                <s:addressLine>The Richmond Green Medical Cen</s:addressLine>
                <s:addressLine>19 The Green</s:addressLine>
                <s:addressLine>Richmond</s:addressLine>
                <s:addressLine>Surrey</s:addressLine>
                <s:postcode>TW91PX</s:postcode>
            </s:address>
            <s:contact type="General">
                <s:telephone>020 83327515</s:telephone>
            </s:contact>
            <s:geographicCoordinates>
                <s:northing>174900</s:northing>
                <s:easting>517800</s:easting>
                <s:longitude>-0.305512266736965</s:longitude>
                <s:latitude>51.4608026642546</s:latitude>
            </s:geographicCoordinates>
            <s:Distance>0.1</s:Distance>
        </s:organisationSummary>
    </content>
</entry>
<entry>
    <id>
        http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33420
    </id>
    <title type="text">Griffiths W</title>
    <updated>2012-04-27T10:33:02Z</updated>
    <link rel="self" title="Griffiths W" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33420?apikey=YAHUGHET"/>
    <link rel="alternate" title="Griffiths W" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=EEC98A8A-B888-4F44-A0B6-DC6ABCBF19CE"/>
    <content type="application/xml">
        <s:organisationSummary>
            <s:name>Griffiths W</s:name>
            <s:address>
                <s:addressLine>Paradise Road Surgery</s:addressLine>
                <s:addressLine>37 Paradise Road</s:addressLine>
                <s:addressLine>Richmond</s:addressLine>
                <s:addressLine>Surrey</s:addressLine>
                <s:postcode>TW91SA</s:postcode>
            </s:address>
            <s:contact type="General">
                <s:telephone>020 89402423</s:telephone>
            </s:contact>
            <s:geographicCoordinates>
                <s:northing>174800</s:northing>
                <s:easting>518100</s:easting>
                <s:longitude>-0.301388352909701</s:longitude>
                <s:latitude>51.4601120315006</s:latitude>
            </s:geographicCoordinates>
            <s:Distance>0.223606797749979</s:Distance>
        </s:organisationSummary>
    </content>
</entry>
<entry>
    <id>
        http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33035
    </id>
    <title type="text">Dr Da Costa</title>
    <updated>2012-04-27T10:33:02Z</updated>
    <link rel="self" title="Dr Da Costa" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33035?apikey=YAHUGHET"/>
    <link rel="alternate" title="Dr Da Costa" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=EDCE215D-6412-4AAB-AFC4-9F37888D413C"/>
    <content type="application/xml">
        <s:organisationSummary>
            <s:name>Dr Da Costa</s:name>
            <s:address>
                <s:addressLine>The Vineyard Surgery</s:addressLine>
                <s:addressLine>35 The Vineyard</s:addressLine>
                <s:addressLine>Richmond</s:addressLine>
                <s:addressLine>Surrey</s:addressLine>
                <s:postcode>TW106PP</s:postcode>
            </s:address>
            <s:contact type="General">
                <s:telephone>020 89480404</s:telephone>
            </s:contact>
            <s:geographicCoordinates>
                <s:northing>174600</s:northing>
                <s:easting>518100</s:easting>
                <s:longitude>-0.301044685875553</s:longitude>
                <s:latitude>51.4581333717098</s:latitude>
            </s:geographicCoordinates>
            <s:Distance>0.360555127546399</s:Distance>
        </s:organisationSummary>
    </content>
</entry>
Was it helpful?

Solution

I've never worked with touchXML, but it may be that you need to set your namespace, like here: Getting the value of an Element in Cocoa using TouchXML

OTHER TIPS

Just check out this , I was able to parse the similar kind of response :

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.rqst=[[WebRqst alloc] init];
    [self.rqst startLoading:[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"PASS UR URL"]]
                       vCtr:self];
}

**// a method to grab the attributes.**
- (void)parseAttributesForElement:(CXMLElement*)element andDictionary:(NSMutableDictionary*)dictionary {
    NSString *strName,*strValue;    
    NSArray *arAttributes = [(CXMLElement*)element attributes];
    for (int i=0; i<arAttributes.count; i++) {
        strName = [[arAttributes objectAtIndex:i] name];
        strValue = [[arAttributes objectAtIndex:i] stringValue];
        if(strName && strValue && [strName length]>0 && [strValue length]>0) {
            [dictionary setValue:strValue forKey:strName];
        }
    }
}

**// a method to parse the node & store in dictionary**
- (void)parseThisNode:(CXMLNode*)node storeInDictionary:(NSMutableDictionary*)dOfNode {
    NSString *strName = [node name];
    NSString *strValue = [node stringValue];
    if(strName && [strName length]>0 && ![strName isEqualToString:@"text"]) {

        NSMutableDictionary *dOfAttributes = [NSMutableDictionary dictionary];

        // if node has value
        if(strValue && [strValue length]>0) {
            [dOfAttributes setValue:strValue forKey:@"value"];
        }

        // if node has attributes
        if([node isKindOfClass:[CXMLElement class]] && [(CXMLElement*)node attributes].count>0) {
            [self parseAttributesForElement:(CXMLElement*)node andDictionary:dOfAttributes];
        }

        // if node has childs
        NSArray *arChildern = [node children];
        if(arChildern.count>0) {
            NSMutableDictionary *dOfTAG=[NSMutableDictionary dictionary];
            for (CXMLNode *nodeChildChild in arChildern) {
                // recursive call of a function
                [self parseThisNode:nodeChildChild storeInDictionary:dOfTAG];
            }
            if([[dOfTAG allKeys] count]>0) [dOfAttributes setValue:dOfTAG forKey:@"child"];
        }

        id valueFK = [dOfNode valueForKey:strName];
        // verify if same node is repeated, add it to array (e.g. link tag is repeated )
        if([valueFK isKindOfClass:[NSMutableArray class]]) {
            NSMutableArray *ar=(NSMutableArray*)valueFK;
            [ar addObject:dOfAttributes];
            [dOfNode setValue:ar forKey:strName];
        } else if([valueFK isKindOfClass:[NSMutableDictionary class]]) {
            NSMutableArray *ar=[NSMutableArray arrayWithObjects:valueFK,dOfAttributes, nil];
            [dOfNode setValue:ar forKey:strName];
        } else {
            [dOfNode setValue:dOfAttributes forKey:strName];
        }
    }
}

**// pass the data to this method & it will return a dictionary**
- (NSDictionary *)startParsingUsingData:(NSData *) data {
    // create a mutable-empty dictionary wich will hold the data
    NSMutableDictionary *dictionaryParsed = [NSMutableDictionary dictionary];

    // verify - do we have proper data for parsing or not
    if(data && [data length]>0) {
        // load a data into XML Document
        CXMLDocument *doc = [[CXMLDocument alloc] initWithData:data options:0 error:nil];

        // grab all the tags of XML
        NSArray *nodes = [doc nodesForXPath:@"*" error:nil];

        // start a loop to goThrough each tag of xml
        for (CXMLNode *nodeFeed in nodes) {

            // verify that you reached to desired tag or not
            if([[nodeFeed name] isEqualToString:@"feed"]) {
                // just write this code to get data parsed & stored in our dictionary
                [self parseThisNode:nodeFeed storeInDictionary:dictionaryParsed];

                // grab the childrens of tag ( as per requirement )
                dictionaryParsed=[[dictionaryParsed valueForKey:@"feed"] valueForKey:@"child"];
            }
        }
    }

    // return the dictionary.
    if([[dictionaryParsed allKeys]count]>0) {
        return [NSDictionary dictionaryWithDictionary:dictionaryParsed];
    } else {
        return nil;
    }
}

// It's my delegate method where I am getting my NSData
    - (void)webRequestReceivedData:(NSData *)data {
        if(data && [data length]>0) {
            NSLog(@"Details are as follows\n%@",
                  [self startParsingUsingData:data]); //This is the method required which will parse the data
        } 
    }

Hope, now you will be able to parse the data.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top