Search code examples
iosnsxmlparserdelegate

what test should be put to get nested element


Here is the case, title exist in two occurrences, before and after entry:

<feed xmlns:im="http://xxx.com/rss" xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <id>http://xxxxx/xml</id><title>xxxxx: Top articles</title><updated>2013-07-20T04:30:05-07:00</updated><link rel="alternate" type="text/html" href="https://xxxx;popId=1"/><link rel="self" href="http://xxxxxxx/xml"/><icon>http://xxxxxxxxxxx</icon><author><name>xxxxxxx</name><uri>http://www.xxxxx.com/xxxxx/</uri></author><rights>Copyright 2001</rights>

        <entry>
            <updated>2013-07-20T04:30:05-07:00</updated>

                <id im:id="621507457">https://xxxxx.xxxx.com/us/album/blurred-lines-feat.-t.i.-pharrell/id621507456?i=621507457&amp;uo=2</id>
                 //I want to get only the title nested in entry tree
                <title>Robin Thicke</title>

What test should be made in didStartElement: protocol method in order to escape any outside the <entry></entry>?

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict{

    if ([elementName isEqualToString:@"title"]) {
      //This is not enough, since it bring also the title value which is outside the entry tree
    }
}

I don't want to rely on an external library like TBXML, I want to know wether this is doable in pure NSXMLParserDelegate?


Solution

  • You have to keep track of whether the parser is currently "inside" an entry element or not. For example, you can add an integer property entryLevel to the class, set it initially to zero and update it in didStartElement and didEndElement:

    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
    {
        if ([elementName isEqualToString:@"entry"]) {
            self.entryLevel++;
        } else if ([elementName isEqualToString:@"title"] && self.entryLevel > 0) {
            // title inside entry
        }
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
    {
        if ([elementName isEqualToString:@"entry"]) {
            self.entryLevel--;
        }
    }