How to use NSXMLParser to parse parent-child elements that have the same name

后端 未结 3 1030
时光取名叫无心
时光取名叫无心 2020-11-29 00:17

Does anyone have some idea how to parse the following xml using event-driven model NSXMLParser class?


   Main 
  

        
3条回答
  •  暖寄归人
    2020-11-29 00:47

    This is a common problem with parsers like this one, of "type SAX", where you have to manually keep track of the current depth of the XML tree you're in. The problem, as always, is that loading the entire tree in a DOM structure in memory can be impossible, depending on the size of the data you want to manipulate.

    The following code shows a class that does this job:

    #import 
    
    @interface Test : NSObject  
    {
    @private
        NSXMLParser *xmlParser;
        NSInteger depth;
        NSMutableString *currentName;
        NSString *currentElement;
    }
    
    - (void)start;
    
    @end
    

    This is the implementation:

    #import "Test.h"
    
    @interface Test ()
    - (void)showCurrentDepth;
    @end
    
    
    @implementation Test
    
    - (void)dealloc
    {
        [currentElement release];
        [currentName release];
        [xmlParser release];
        [super dealloc];
    }
    
    - (void)start
    {
        NSString *xml = @"MainChild 1Child 2";
        xmlParser = [[NSXMLParser alloc] initWithData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
        [xmlParser setDelegate:self];
        [xmlParser setShouldProcessNamespaces:NO];
        [xmlParser setShouldReportNamespacePrefixes:NO];
        [xmlParser setShouldResolveExternalEntities:NO];
        [xmlParser parse];
    
    }
    
    #pragma mark -
    #pragma mark NSXMLParserDelegate methods
    
    - (void)parserDidStartDocument:(NSXMLParser *)parser 
    {
        NSLog(@"Document started", nil);
        depth = 0;
        currentElement = nil;
    }
    
    - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 
    {
        NSLog(@"Error: %@", [parseError localizedDescription]);
    }
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
      namespaceURI:(NSString *)namespaceURI 
     qualifiedName:(NSString *)qName 
        attributes:(NSDictionary *)attributeDict
    {
        [currentElement release];
        currentElement = [elementName copy];
    
        if ([currentElement isEqualToString:@"Node"])
        {
            ++depth;
            [self showCurrentDepth];
        }
        else if ([currentElement isEqualToString:@"name"])
        {
            [currentName release];
            currentName = [[NSMutableString alloc] init];
        }
    }
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
      namespaceURI:(NSString *)namespaceURI 
     qualifiedName:(NSString *)qName
    {
    
        if ([elementName isEqualToString:@"Node"]) 
        {
            --depth;
            [self showCurrentDepth];
        }
        else if ([elementName isEqualToString:@"name"])
        {
            if (depth == 1)
            {
                NSLog(@"Outer name tag: %@", currentName);
            }
            else 
            {
                NSLog(@"Inner name tag: %@", currentName);
            }
        }
    }        
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    {
        if ([currentElement isEqualToString:@"name"]) 
        {
            [currentName appendString:string];
        } 
    }
    
    - (void)parserDidEndDocument:(NSXMLParser *)parser 
    {
        NSLog(@"Document finished", nil);
    }
    
    #pragma mark -
    #pragma mark Private methods
    
    - (void)showCurrentDepth
    {
        NSLog(@"Current depth: %d", depth);
    }
    
    @end
    

    This is the result of running a command line tool that triggers the "start" method above:

    Document started
    Current depth: 1
    Outer name tag: Main
    Current depth: 2
    Inner name tag: Child 1
    Current depth: 1
    Current depth: 2
    Inner name tag: Child 2
    Current depth: 1
    Current depth: 0
    Document finished
    

提交回复
热议问题