2011-04-28 27 views
1

我讀一個xml一些領域,例如:的NSXMLParser檢索從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?

在此先感謝您的幫助!

回答

2

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更多的方法,如果你需要一個更復雜的分析

+0

您好,感謝您的幫助。通過您的解決方案,整個元素「文檔」立即被讀取,這意味着所有的標籤都在一起。 – baboso 2011-04-28 16:16:23

+0

我用我用來分析任何類型的XML文本的代碼更新了我的答案! – Sylverb 2011-04-28 19:49:43

+0

非常好的你提供這個。 – 2016-11-14 22:56:34