NSXMLParser retrieving wrong data from XML tags

前端 未结 1 452
深忆病人
深忆病人 2021-01-24 14:34

I am reading a xml with some fields, for example:

http://myurl.com/noticias/redirect.html?document=xx222&usuario=44yyy&url=http%3A%2F%2Fwww.en         


        
相关标签:
1条回答
  • 2021-01-24 15:12

    foundCharacters can be called several times for one field ! You should create a temporary NSMutableString and append foundcaracters result !

    // Start of element
    - (void)parser:(NSXMLParser *)parser
    didStartElement:(NSString *)elementName
      namespaceURI:(NSString *)namespaceURI
     qualifiedName:(NSString *)qName
        attributes:(NSDictionary *)attributeDict
    {
        if ([elementName isEqualToString:@"document"]){
            NSLog(@"doc found");
    
            if (temp != nil) {
                [temp release];
            }
    
            // Alloc temp string
            currentNodeContent = [[NSMutableString alloc] init];
    
    
        }
    }
    
    // Found Character
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSMutableString *)string
    {
        if (currentNodeContent != nil) {
            [currentNodeContent appendString:[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
        }
    }
    
    
    // End Element
    - (void) parser:(NSXMLParser *)parser
      didEndElement:(NSString *)elementName
       namespaceURI:(NSString *)namespaceURI
      qualifiedName:(NSString *)qName
    {
        if ([elementName isEqualToString:@"url"]){
    
            NSLog(@"%@", currentNodeContent);
    
        }
        if ([elementName isEqualToString:@"title"]){
    
            NSLog(@"%@", currentNodeContent);
    
        }
    
    
    
        if ([elementName isEqualToString:@"document"]){
            [currentNodeContent release];
            currentNodeContent = nil;
        }
    
        // Release temp string
        [currentNodeContent release];
        currentNodeContent = nil;
    
    
    }
    

    Be sure to declare currentNodeContent as a NSMutableString and not a NSString !

    Here is the xml parser code I'm using in my projects :

    //
    //  XMLParser.h
    //
    
    #import <Foundation/Foundation.h>
    #import "XMLNode.h"
    
    #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2
    @interface XMLParser : NSObject <NSXMLParserDelegate> {
    #else
    @interface XMLParser : NSObject {
    #endif
        XMLNode *rootElement;
        XMLNode *tempElement;
        NSMutableString *temp;
        NSMutableArray *elements;
    }
    
    - (NSObject *)parseData:(NSData *)data;
    
    // NSXMLParser delegate implementation
    - (void)parserDidStartDocument:(NSXMLParser *)parser;
    - (void)parserDidEndDocument:(NSXMLParser *)parser;
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict;
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName;
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
    
    @end
    

    -

    //
    //  XMLParser.m
    //
    
    #import "XMLParser.h"
    
    
    @implementation XMLParser
    
    - (NSObject *)parseData:(NSData *)data
    {
        NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
        [parser setDelegate:self];
        [parser setShouldResolveExternalEntities:YES];
    
        if (![parser parse]) {
            if ([[parser parserError] code] == NSXMLParserUnknownEncodingError) {
                // If encoding is "us-ascii" replace encoding with something known (as NSXMLParser is not supporting this encoding)
                NSString *oldString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
                NSString *newEncodingString = [oldString stringByReplacingOccurrencesOfString:@"encoding=\"us-ascii\"" withString:@"encoding=\"iso-8859-1\"" options:0 range:NSMakeRange(0,100)];
                newEncodingString = [newEncodingString stringByReplacingOccurrencesOfString:@"encoding=\"windows-1251\"" withString:@"encoding=\"iso-8859-1\"" options:0 range:NSMakeRange(0,100)];
    
                [oldString release];
                NSData *nameData = [newEncodingString dataUsingEncoding:NSASCIIStringEncoding];
                NSXMLParser *parser2 = [[NSXMLParser alloc] initWithData:nameData];
                [parser2 setDelegate:self];
                [parser2 setShouldResolveExternalEntities:YES];
                if (![parser2 parse]) {
                    DLog(@"parseXML error : %@",[[parser2 parserError] localizedDescription]);
                }
                [parser2 release];
    
            } else {
                DLog(@"parseXML error : %@",[[parser parserError] localizedDescription]);
            }
    
        }
        [parser release];
    
        return rootElement;
    }
    
    
    - (void)dealloc
    {
        if (tempElement != nil) {
            [tempElement release];
        } 
        if (rootElement != nil) {
            [rootElement release];
        }
        if (temp != nil) {
            [temp release];
        }
        if (elements != nil) {
            [elements release];
        }
    
        [super dealloc];
    }
    
    
    // NSXMLParser delegate implementation
    
    
    - (void)parserDidStartDocument:(NSXMLParser *)parser
    {
        if (elements != nil) {
            [elements release];
        }
        elements = [[NSMutableArray alloc] init];
        if (tempElement != nil) {
            [tempElement release];
            tempElement = nil;
        }
        if (temp != nil) {
            [temp release];
            temp = nil;
        }
        if (rootElement != nil) {
            [rootElement release];
            rootElement = nil;
        }
    }
    
    
    - (void)parserDidEndDocument:(NSXMLParser *)parser
    {
       if (elements != nil) {
            [elements release];
            elements = nil;
        }
        if (tempElement != nil) {
            [tempElement release];
            tempElement = nil;
        }
        if (temp != nil) {
            [temp release];
            temp = nil;
        }
    }
    
    
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
      namespaceURI:(NSString *)namespaceURI
     qualifiedName:(NSString *)qualifiedName
        attributes:(NSDictionary *)attributeDict
    {
        XMLNode *element = [[[XMLNode alloc] initWithName:elementName] autorelease];
        [element setAttributes:attributeDict];
        if (tempElement != nil) {
            [tempElement addChild:element];
            [elements addObject:tempElement];
            [tempElement release];
        } else {
            rootElement = [element retain];
        }
    
        tempElement = [element retain];
        if (temp != nil) {
            [temp release];
        }
        temp = [[NSMutableString alloc] init];
    }
    
    
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
      namespaceURI:(NSString *)namespaceURI
     qualifiedName:(NSString *)qName
    {
        [tempElement setContent:temp];
        [temp release];
        temp = nil;
        [tempElement release];
        tempElement = nil;
        if ([elements count] > 0) {
            tempElement = [[elements lastObject] retain];
            [elements removeLastObject];
        }
    }
    
    
    - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
    {
        if (temp != nil) {
            [temp appendString:string];
        }
    }
    
    @end
    

    -

    //
    //  XMLNode.h
    //
    
    #import <Foundation/Foundation.h>
    
    /**
     * XMLNode represents an XML data node.
     *
     * Every node can contain multiple children, attributes, a content string
     * and an element name. An XML document is represented using a reference
     * to the document root node.
     * @ingroup Webservice
     */
    @interface XMLNode : NSObject {
    
        NSMutableArray *children;
        NSDictionary *attributes;
        NSString *content;
        NSString *elementName;
    
    }
    
    /**
     * Return an initialized XMLNode.
     * @param name The element name of the node.
     */
    - (id)initWithName:(NSString *)name;
    
    /**
     * Set the node attributes.
     * @param dictionary A dictionary containing the attributes.
     */
    - (void)setAttributes:(NSDictionary *)dictionary;
    
    /**
     * Set the content as string.
     * @param string The content as string.
     */
    - (void)setContent:(NSString *)string;
    
    /**
     * Add a child node.
     * @param xmlElement The child node.
     */
    - (void)addChild:(XMLNode *)xmlElement;
    
    /**
     * Return a specific attribute.
     * @param name The attribute name.
     * @return The attribute for the specified name or nil.
     */
    - (NSString *)attributeForName:(NSString *)name;
    
    /**
     * Return a child at a specific index.
     * 
     * If the index is out of the bounds, an NSRangeException is thrown.
     * @param index The position of the child (by document order).
     * @return The child at index
     * @see childElementsCount
     */
    - (XMLNode *)childElementAtIndex:(int)index;
    
    /**
     * Return a child with a certain name.
     * @param name The name of the element.
     * @return The element or nil if not available.
     */
    - (XMLNode *)childWithName:(NSString *)name;
    - (XMLNode *)childWithName:(NSString *)name atIndex:(NSInteger)index;
    
    /** 
     * Return the number of child nodes.
     * @return The number of child nodes.
     */
    - (int)childElementsCount;
    - (int)childWithNameElementsCount:(NSString *)name;
    
    /** 
     * Return the node content.
     * @return The node content as string.
     */
    - (NSString *)content;
    
    /**
     * Get the name of the xml element.
     * @return The name of the element.
     */
    - (NSString *)name;
    
    - (void)dealloc;
    
    @end
    

    -

    //
    //  XMLNode.m
    //
    
    #import "XMLNode.h"
    
    
    @implementation XMLNode
    - (id)initWithName:(NSString *)name
    {
        self = [super init];
        elementName = [name copy];
        children = [[NSMutableArray alloc] init];
        return self;
    }
    
    
    - (void)setAttributes:(NSDictionary *)dictionary
    {
        if (attributes != nil) {
            [attributes release];
        }
        attributes = [dictionary retain];
    }
    
    
    - (void)setContent:(NSString *)string
    {
        if (content != nil) {
            [content release];
        }
        content = [string retain];
    }
    
    - (void)addChild:(XMLNode *)xmlElement
    {
        [children addObject:xmlElement];
    }
    
    
    - (NSString *)attributeForName:(NSString *)name
    {
        return [attributes objectForKey:name];
    }
    
    
    - (XMLNode *)childElementAtIndex:(int)index
    {
        return [children objectAtIndex:index];
    }
    
    
    - (XMLNode *)childWithName:(NSString *)name
    {
        int i;
        for (i=0; i < [children count]; ++i) {
            XMLNode *child = [children objectAtIndex:i];
            if ([[[child name] lowercaseString] isEqualToString:[name lowercaseString]]) {
                return child;
            }
        }
    
        return nil;
    }
    
    - (XMLNode *)childWithName:(NSString *)name atIndex:(NSInteger)index
    {
        int i;
        int count = 0;
        for (i = 0; i < [children count]; ++i) {
            XMLNode *child = [children objectAtIndex:i];
            if ([[[child name] lowercaseString] isEqualToString:[name lowercaseString]]) {
                if (count == index)
                    return child;
                count ++;
            }
        }
    
        return nil;
    }
    
    - (int)childElementsCount
    {
        return [children count];
    }
    
    - (int)childWithNameElementsCount:(NSString *)name
    {
        int i;
        int count = 0;
        for (i = 0; i < [children count]; ++i) {
            XMLNode *child = [children objectAtIndex:i];
            if ([[[child name] lowercaseString] isEqualToString:[name lowercaseString]]) {
                count ++;
            }
        }
    
        return count;
    }
    
    
    - (NSString *)content
    {
        return content;
    }
    
    
    - (NSString *)name
    {
        return elementName;
    }
    
    
    - (void)dealloc
    {
        if (content != nil) {
            [content release];
        }
        if (children != nil) {
            [children release];
        }
        if (attributes != nil) {
            [attributes release];
        }
    
        [super dealloc];
    }
    
    @end
    

    use this as following (this sample is to analyze a rss feed :

    XMLParser *parser = [[XMLParser alloc] init];
    NSObject *rss = [parser parseData:rssFeed];
    feedItems = [(XMLNode *)rss childWithName:@"channel"];
    if (feedItems) {
        NSLog(@"%@",[[feedItems childWithName:@"title"] content]);
    }
    [parser release];
    

    Check XMLNode.h for more methods if you need a more complex analysis

    0 讨论(0)
提交回复
热议问题