【问题标题】:How to grab an XML element and store it? Objective C如何获取 XML 元素并存储它?目标 C
【发布时间】:2013-07-26 09:09:49
【问题描述】:

我正在尝试从网站获取令牌。验证成功后,将显示一个 XML 文档。

我创建了一个如下图所示的连接:

NSString *strURLQueryString = [NSString stringWithFormat:@"%@?username=%@&password=%@", kURL_LOGIN, nameString, passwordString];
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:strURLQueryString]
                                                cachePolicy:NSURLRequestUseProtocolCachePolicy
                                            timeoutInterval:60.0];

为了显示输出,我使用了这个:

unsigned char byteBuffer[[receivedData length]];
[receivedData getBytes:byteBuffer];
NSLog(@"Output: %s", (char *)byteBuffer);

所以返回文档的部分输出如下图所示:

    <status>0</status><reason>User fetched.</reason><token>9cb7396dccabe68c067521db219afb83</token>

我已经阅读了许多 XML 解析实现,但我无法实现它,因为它不能满足我的需要,我只是无法理解它的解释的复杂性。

如果有人能给我一个很好的建议,我将不胜感激。

【问题讨论】:

  • 使用 NSXMLParser。它很容易理解。它有一些非常简单的委托方法。所以试试吧。
  • 使用 NSXMLParser 解析

标签: ios objective-c xml parsing token


【解决方案1】:
- (XMLParserViewController *) initXMLParser {


    appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    return self;
}

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

    if([elementName isEqualToString:@"Books"]) {
        appDelegate.books = [[NSMutableArray alloc] init];
    }
    else if([elementName isEqualToString:@"Book"])
    {

        aBook = [[Books alloc] init];

    }

    NSLog(@"Processing Element: %@", elementName);
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

    if(!currentElementValue)
        currentElementValue = [[NSMutableString alloc] initWithString:string];
    else
        [currentElementValue appendString:string];

    NSLog(@"Processing Value: %@", currentElementValue);

}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
  namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {

    if([elementName isEqualToString:@"Books"])
        return;

    if([elementName isEqualToString:@"Book"])
    {
       [appDelegate.books addObject:aBook];        
          aBook = nil;
    }
    else if([elementName isEqualToString:@"name"])
    {
        aBook.name=currentElementValue;
    }
    else if([elementName isEqualToString:@"address"])
    {
        aBook.address=currentElementValue;
    }
    else if([elementName isEqualToString:@"country"])
    {
        aBook.country=currentElementValue;
    }        

    currentElementValue = nil;


    NSLog(@"%@",aBook.name);
    NSLog(@"%@",aBook.address);
    NSLog(@"%@",aBook.country);
}

试试这个,,我希望这有效....

【讨论】:

    【解决方案2】:

    相关的 NSXMLParserDelegate 方法:

    -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName //etc 
    { _inToken = [elementName isEqualToString:@"token"]; }
    
    -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName  //etc
    { _inToken = NO; }
    
    -(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
      if (_inToken) {
          _token = string;
          [parser abortParsing];
      }
    }
    

    【讨论】:

      【解决方案3】:

      您应该使用 XML 解析器。 它易于使用,请执行以下所有步骤以获得最佳效果:

      从 NSXMLParser 创建 XMLParser 类的子类,这样你就有了 NSXMLParser.h 和 NSXMLParser.m 类

      你的 .h 类必须是这样的:

      #import <Foundation/Foundation.h>
      
      @interface XMLParser : NSXMLParser <NSXMLParserDelegate>{
      
          NSUInteger parsedCounter;
          BOOL accumulatingParsedCharacterData;
          BOOL didAbortParsing;
      }
      @property (nonatomic, strong) NSMutableString *currentParsedCharacterData;
      @property (nonatomic, strong) NSMutableArray *currentParsedCharacterArray;
      @end
      

      还有 .m 类:

      #import "XMLParser.h"
      
      @implementation XMLParser
      
      #pragma mark Parser constants
      
      // Limit the number of parsed data to 100.
      static const NSUInteger kMaximumNumberOfFilesToParse = 100;
      
      static NSUInteger const kSizeOfFileBatch = 10;
      
      // Reduce potential parsing errors by using string constants declared in a single place.
      static NSString * const kEntryElementName = @"dlResult";
      static NSString * const kStringElementName = @"string";
      
      
      #pragma mark NSXMLParser delegate methods
      
      - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
      
      //    NSLog(@"didStart");
          // If the number of parsed earthquakes is greater than kMaximumNumberOfEarthquakesToParse, abort the parse.
          if (parsedCounter >= kMaximumNumberOfFilesToParse) {
              // Use the flag didAbortParsing to distinguish between this deliberate stop and other parser errors.
              didAbortParsing = YES;
              [self abortParsing];
          }
          if ([elementName isEqualToString:kEntryElementName]) {
              _currentParsedCharacterArray = [[NSMutableArray alloc]init];
      
          } else if ([elementName isEqualToString:kStringElementName]) {
      
              accumulatingParsedCharacterData = YES;
              _currentParsedCharacterData = [[NSMutableString alloc]init];
          }
      }
      
      // return string between tags
      - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
      //    NSLog(@"foundCh");
          if (accumulatingParsedCharacterData) {
              // If the current element is one whose content we care about, append 'string'
              // to the property that holds the content of the current element.
              [_currentParsedCharacterData appendString:string];
              NSLog(@"currentParsedCharacterData:%@",_currentParsedCharacterData);
          }
      }
      
      - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
      //    NSLog(@"didEnd");
      
          if ([elementName isEqualToString:kStringElementName]) {
              [_currentParsedCharacterArray addObject:_currentParsedCharacterData];
      
          }
          accumulatingParsedCharacterData = NO;
      }
      
      - (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
             if (didAbortParsing == NO) {
              // Pass the error to the main thread for handling.
              [self performSelectorOnMainThread:@selector(handleError:) withObject:parseError waitUntilDone:NO];
          }
      }
      
      @end
      

      .m 类中有两个 const 字符串:

      static NSString * const kEntryElementName = @"dlResult";
      static NSString * const kStringElementName = @"string";
      

      那些是字符串标签,你应该实现的标签是“status”、“reason”、“token”

      从连接类,向 XMLParser 类发送数据连接,如下所示:

      @autoreleasepool {
      
          // It's also possible to have NSXMLParser download the data, by passing it a URL, but this is not desirable
          // because it gives less control over the network, particularly in responding to connection errors.
          //
              XMLParser *parser = [[XMLParser alloc] initWithData:data];
      
              parser.currentParsedCharacterArray = [NSMutableArray array];
              parser.currentParsedCharacterData = [NSMutableString string];
              [parser setDelegate:parser];
      
              [parser parse];
      
              // depending on the total number of earthquakes parsed, the last batch might not have been a "full" batch, and thus
              // not been part of the regular batch transfer. So, we check the count of the array and, if necessary, send it to the main thread.
      
              if ([parser.currentParsedCharacterArray count] > 0) {
                  // send parsed data to another class or ...
                  // parser.currentParsedCharacterArray is parsed data
              }
              parser.currentParsedCharacterArray = nil;
              parser.currentParsedCharacterData = nil;
          }
      

      如果你有任何问题,问我!

      【讨论】:

      • 您好,谢谢您的建议。只是为了让您知道,我大约 3 天前才开始阅读有关 Objective -c 的内容。因此,如果我的问题听起来很愚蠢,我深表歉意。我在哪里指定“令牌”?而且,我如何在主文件中实际实现它。我已经阅读了 NSXML 文档,但我还是不太明白。
      • 哦,我不明白下面的两行:“elementName isEqualToString:kEntryElementName”和“[elementName isEqualToString:kStringElementName]”。他们为什么要寻找“dlResult”和“string”?
      • 没关系!我知道在第一个月用 Objective-c 编码并不容易!
      • 您可以在主类中实现XML Parser,但我认为这对您来说并不容易!尝试通过转到 File-> New -> File 来创建一个新类,然后在 ios 部分下选择 Cocoa Touch,选择 Objective-C 类!单击下一步并通过“NSXMLParser”填充子类并通过“XMLParser”填充类,单击下一步。现在你创建这个类!不要忘记在你的主类上添加这个类的标题。
      • XML是一种标签语言,数据在标签之间,如fashapouriIranPersian,因此要解析此标签之间的数据,您应该从标签中定义常量 static NSString * const kStringElementName = @"name";静态 NSString * const kStringElementFamily = @"family";静态 NSString * const kStringElementCountry = @"country";静态 NSString * const kStringElementLanguage = @"language";并在 parser:didEndElement:namespaceURI:qualifiedName: 方法中使用它们将 _currentParsedCharacterData 分配给正确的标签!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      相关资源
      最近更新 更多