【问题标题】:NSXMLParser retrieving wrong data from XML tagsNSXMLParser 从 XML 标记中检索错误数据
【发布时间】:2011-08-14 19:53:40
【问题描述】:

我正在读取包含一些字段的 xml,例如:

<url>http://myurl.com/noticias/redirect.html?document=xx222&usuario=44yyy&url=http%3A%2F%2Fwww.environmental-expert.com%2FresultEachPressRelease.aspx%3Fcid%3D23745%26codi%3D234441%26lr%3D1</url>

<title>The world water report – supplies falling, Tensions Rising</title>

输出是:

2011-04-28 17:08:02.191 MyProject[12093:207] doc found

2011-04-28 17:08:02.192 MyProject[12093:207] url=http%3A%2F%2Fwww.environmental-expert.com%2FresultEachPressRelease.aspx%3Fcid%3D23745%26codi%3D234441%26lr%3D1

2011-04-28 17:08:02.193 MyProject[12093:207] – supplies falling, Tensions Rising

与 xml 文件中的数据不匹配。

我的解析器有以下方法:

// 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");

    }
}

// Found Character
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSMutableString *)string
{
    currentNodeContent = [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;
    }

}

会不会和foundCharacters函数有关?

提前感谢您的帮助!

【问题讨论】:

    标签: iphone xml ios ios4 nsxmlparser


    【解决方案1】:

    foundCharacters 可以为一个字段多次调用! 您应该创建一个临时 NSMutableString 并附加 foundcaracters 结果!

    // 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;
    
    
    }
    

    确保将 currentNodeContent 声明为 NSMutableString 而不是 NSString!

    这是我在项目中使用的 xml 解析器代码:

    //
    //  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
    

    如下使用(此示例用于分析 rss 提要:

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

    如果您需要更复杂的分析,请查看 XMLNode.h 以获取更多方法

    【讨论】:

    • 您好,感谢您的帮助。使用您的解决方案,一次读取整个元素“文档”,这意味着所有标签都在一起。
    • 我确实用我用来分析任何类型的 xml 文本的代码更新了我的答案!
    • 非常高兴你能提供这个。
    • 对于审阅者来说,OP 错误地使用了 Childs 而不是 Children。我纠正了这一点。为什么会被拒绝?
    猜你喜欢
    • 1970-01-01
    • 2017-11-23
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多