你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS編程技術 >> iOS IM開發准備工作(一)XML解析

iOS IM開發准備工作(一)XML解析

編輯:IOS編程技術

  關於XML解析的blog有很多,我本來不想寫的;不過我發現有一些細節他們都沒有說,我這裡就多說一些細節。

  我們在哪些地方用XML:現在json用的這麼多,使用XML通訊的已經不多了。我遇到的場景是,我們的服務器有很多個,需要用戶去選擇。那麼我們就需要定期維護一個服務器列表,這個服務器列表的配置文件我需要每次下載。自然我就需要解析這一個文件。

  XML解析有兩種模式SAX和DOM。我用的是系統的 NSXMLParser 它是SAX解析。

  我寫了一個工具類,先貼一下代碼,下面會有一些說明

.h

 #import <Foundation/Foundation.h>
 
 typedef NS_ENUM(NSInteger,xmlModelName){// 這裡我對我的XML文件做了區別 因為要解析表情和服務器列表兩種
     xmlModelNameFace,
     xmlModelNameServer,
 };
 @interface XMLParser : NSObject<NSXMLParserDelegate>
 // 這個是回調的Block
 @property(nonatomic,copy)void (^returnParseArray)(NSArray * returnArray);
 @property(nonatomic,readonly)xmlModelName currentModelName;
 
 - (instancetype)initWithFilePath:(NSString *)path fileType:(NSString *)fileType modelName:(xmlModelName)modelName;
 
 - (void)startWithFilePath:(NSString *)path fileType:(NSString *)fileType;
 @end

.m

 #import "XMLParser.h"
 #import "FaceModel.h"
 #import "ToolClient.h"
 #import "ServerModel.h"
 @implementation XMLParser{
     NSMutableArray * faceArray;
     NSMutableArray * serverArray;
 }
 
 @synthesize currentModelName;
 - (instancetype)initWithFilePath:(NSString *)path fileType:(NSString *)fileType modelName:(xmlModelName)modelName{
     self = [super init];
     if(self){
         currentModelName = modelName;
     }
     return self;
 }
 
 - (void)startWithFilePath:(NSString *)path fileType:(NSString *)fileType {
     [self parseWithPath:path type:fileType];
 }
 //
 - (void)parseWithPath:(NSString *)filePath type:(NSString *)fileType{
     if (currentModelName == xmlModelNameFace) {
         faceArray = [[NSMutableArray alloc]init];
     }else if(currentModelName == xmlModelNameServer){
         serverArray = [[NSMutableArray alloc]init];
     }
     NSData *xmlData = [[NSData alloc] initWithContentsOfFile:filePath];
     if(xmlData && xmlData.length > 10){
         NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
         [parser setShouldProcessNamespaces:NO];
         [parser setShouldReportNamespacePrefixes:NO];
         [parser setShouldResolveExternalEntities:NO];
         [parser setDelegate:self];
         BOOL success = [parser parse];
         if(success) {
             [self parseSuccess];
         }else {
             [ToolClient activityShowMessage:@"XML解析失敗" inView:[UIApplication sharedApplication].windows[0]];
         }
     }else {
         [ToolClient activityShowMessage:@"XML解析失敗" inView:[UIApplication sharedApplication].windows[0]];
     }
 }
 // 成功後的回調
 - (void)parseSuccess {
     if(self.returnParseArray){
         if (currentModelName == xmlModelNameFace) {
             self.returnParseArray(faceArray);
         }else if(currentModelName == xmlModelNameServer){
             self.returnParseArray(serverArray);
         }
     }
 }
 #pragma mark - NSXMLParserDelegate
 
 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
   namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
     attributes:(NSDictionary *)attributeDict {
     //    NSLog(@"Name:%@",elementName);
     
     if([elementName isEqualToString:@"face"] && currentModelName == xmlModelNameFace) {
         FaceModel * faceModel = [[FaceModel alloc]init];
         faceModel.kID = [attributeDict[@"id"]intValue];
         faceModel.kName = attributeDict[@"name"];
         faceModel.kImage = attributeDict[@"file"];
         [faceArray  addObject:faceModel];
         faceModel = nil;
     }else if([elementName isEqualToString:@"Server"] && currentModelName == xmlModelNameServer){
         ServerModel * sModel = [[ServerModel alloc]init];
         sModel.serverName = attributeDict[@"name"];
         sModel.serverIP = attributeDict[@"ChatServerIP"];
         sModel.chatPort = attributeDict[@"chatPort"];
         sModel.fileServerIP = attributeDict[@"fileServerIP"];
         sModel.filePort = attributeDict[@"filePort"];
         [serverArray addObject:sModel];
         sModel = nil;
     }
 }
 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string  {
     //    NSLog(@"value:%@",string);
 }
 - (void)parserDidEndDocument:(NSXMLParser *)parser {
     //     //    NSLog(@"%@",faceArray);
     
 }
 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
     //    NSLog(@"elementName:%@",elementName);
     //    NSLog(@"qualifiedName:%@",qName);
     //
     //    NSLog(@"NSXMLParserDone");
     //    NSLog(@"%@",faceArray);
     //    NSLog(@"%i",(int)faceArray.count);
     
 }
 @end

現在我來說一下XML解析的設置裡面那3個設置為NO的參數是什麼作用

  [parser setShouldProcessNamespaces:NO]; [parser setShouldReportNamespacePrefixes:NO]; [parser setShouldResolveExternalEntities:NO]; 

  第一個 setShouldProcessNamespaces 這個屬性設置為YES的話,這兩個方法會有值輸出:parser:didStartElement:namespaceURI:qualifiedName:attributes: 和 parser:didEndElement:namespaceURI:qualifiedName: 這兩個在解析過程中都是都是可以看到裡面的節點或字段的名字的。我覺得調試的時候可以用一下。

  第二個 setShouldReportNamespacePrefixes 這個屬性設置為YES的話,這兩個方法會有值輸出:parser:didStartMappingPrefix:toURI: 和 parser:didEndMappingPrefix: 這個我覺得完全沒有必要用它

  第三個 setShouldResolveExternalEntities 這個屬性設置為YES的話,這個方法會有值輸出:parser:foundExternalEntityDeclarationWithName:publicID:systemID: 其中publicID 和systemID 都是XML文檔的特有的標識。官方文檔對這個兩個的變量都是這麼說的:

You may access this property once a parsing operation has begun or after an error occurs.

也就是當XML解析已經開始或者出現錯誤的時候,再去看它。也就是說如果你的XML寫的夠好 你就忽略它吧。

  上面的代碼是工具類,下面這段會告訴你這段代碼怎麼用:

 // 解析文件 
 - (void)parseFile:(NSString *)filepath{
     NSLog(@"filepath%@",filepath);// 文件的路徑
     if(data.length>10){// 簡單的長度檢測
         __weak SelectServerViewController * ws = self;// 弱引用
         // do parse
         XMLParser * xp = [[XMLParser alloc]initWithFilePath:filepath fileType:@"xml" modelName:xmlModelNameServer];
         // 先設置回調
         xp.returnParseArray = ^(NSArray * array){
             // 回調的結果 去給tableView 展示
             [ws gotDataArray:array];
         };
         // 再開始解析
         [xp startWithFilePath:filepath fileType:@"xml"];
     }
    
 }
 
 - (void)gotDataArray:(NSArray *)array {
     if(array){
 //        NSLog(@"array:%@",array);
         dataArray = [array mutableCopy];
         [myTableView reloadData];
     }
 }

XML解析我就寫這麼多了,給一個建議 解析的時候用一個Model來存儲數據,後續的使用會很方便。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved