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

来源:http://www.cnblogs.com/akforsure/archive/2016/02/14/5189370.html
-Advertisement-
Play Games

關於XML解析的blog有很多,我本來不想寫的;不過我發現有一些細節他們都沒有說,我這裡就多說一些細節。 我們在哪些地方用XML:現在json用的這麼多,使用XML通訊的已經不多了。我遇到的場景是,我們的伺服器有很多個,需要用戶去選擇。那麼我們就需要定期維護一個伺服器列表,這個伺服器列表的配置文件我


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

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

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

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

.h

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

.m

 1 #import "XMLParser.h"
 2 #import "FaceModel.h"
 3 #import "ToolClient.h"
 4 #import "ServerModel.h"
 5 @implementation XMLParser{
 6     NSMutableArray * faceArray;
 7     NSMutableArray * serverArray;
 8 }
 9 
10 @synthesize currentModelName;
11 - (instancetype)initWithFilePath:(NSString *)path fileType:(NSString *)fileType modelName:(xmlModelName)modelName{
12     self = [super init];
13     if(self){
14         currentModelName = modelName;
15     }
16     return self;
17 }
18 
19 - (void)startWithFilePath:(NSString *)path fileType:(NSString *)fileType {
20     [self parseWithPath:path type:fileType];
21 }
22 //
23 - (void)parseWithPath:(NSString *)filePath type:(NSString *)fileType{
24     if (currentModelName == xmlModelNameFace) {
25         faceArray = [[NSMutableArray alloc]init];
26     }else if(currentModelName == xmlModelNameServer){
27         serverArray = [[NSMutableArray alloc]init];
28     }
29     NSData *xmlData = [[NSData alloc] initWithContentsOfFile:filePath];
30     if(xmlData && xmlData.length > 10){
31         NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
32         [parser setShouldProcessNamespaces:NO];
33         [parser setShouldReportNamespacePrefixes:NO];
34         [parser setShouldResolveExternalEntities:NO];
35         [parser setDelegate:self];
36         BOOL success = [parser parse];
37         if(success) {
38             [self parseSuccess];
39         }else {
40             [ToolClient activityShowMessage:@"XML解析失敗" inView:[UIApplication sharedApplication].windows[0]];
41         }
42     }else {
43         [ToolClient activityShowMessage:@"XML解析失敗" inView:[UIApplication sharedApplication].windows[0]];
44     }
45 }
46 // 成功後的回調
47 - (void)parseSuccess {
48     if(self.returnParseArray){
49         if (currentModelName == xmlModelNameFace) {
50             self.returnParseArray(faceArray);
51         }else if(currentModelName == xmlModelNameServer){
52             self.returnParseArray(serverArray);
53         }
54     }
55 }
56 #pragma mark - NSXMLParserDelegate
57 
58 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
59   namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
60     attributes:(NSDictionary *)attributeDict {
61     //    NSLog(@"Name:%@",elementName);
62     
63     if([elementName isEqualToString:@"face"] && currentModelName == xmlModelNameFace) {
64         FaceModel * faceModel = [[FaceModel alloc]init];
65         faceModel.kID = [attributeDict[@"id"]intValue];
66         faceModel.kName = attributeDict[@"name"];
67         faceModel.kImage = attributeDict[@"file"];
68         [faceArray  addObject:faceModel];
69         faceModel = nil;
70     }else if([elementName isEqualToString:@"Server"] && currentModelName == xmlModelNameServer){
71         ServerModel * sModel = [[ServerModel alloc]init];
72         sModel.serverName = attributeDict[@"name"];
73         sModel.serverIP = attributeDict[@"ChatServerIP"];
74         sModel.chatPort = attributeDict[@"chatPort"];
75         sModel.fileServerIP = attributeDict[@"fileServerIP"];
76         sModel.filePort = attributeDict[@"filePort"];
77         [serverArray addObject:sModel];
78         sModel = nil;
79     }
80 }
81 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string  {
82     //    NSLog(@"value:%@",string);
83 }
84 - (void)parserDidEndDocument:(NSXMLParser *)parser {
85     //86     //    NSLog(@"%@",faceArray);
87     
88 }
89 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
90     //    NSLog(@"elementName:%@",elementName);
91     //    NSLog(@"qualifiedName:%@",qName);
92     //
93     //    NSLog(@"NSXMLParserDone");
94     //    NSLog(@"%@",faceArray);
95     //    NSLog(@"%i",(int)faceArray.count);
96     
97 }
98 @end

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

 1 [parser setShouldProcessNamespaces:NO]; 2 [parser setShouldReportNamespacePrefixes:NO]; 3 [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寫的夠好 你就忽略它吧。

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

 1 // 解析文件 
 2 - (void)parseFile:(NSString *)filepath{
 3     NSLog(@"filepath%@",filepath);// 文件的路徑
 4     if(data.length>10){// 簡單的長度檢測
 5         __weak SelectServerViewController * ws = self;// 弱引用
 6         // do parse
 7         XMLParser * xp = [[XMLParser alloc]initWithFilePath:filepath fileType:@"xml" modelName:xmlModelNameServer];
 8         // 先設置回調
 9         xp.returnParseArray = ^(NSArray * array){
10             // 回調的結果 去給tableView 展示
11             [ws gotDataArray:array];
12         };
13         // 再開始解析
14         [xp startWithFilePath:filepath fileType:@"xml"];
15     }
16    
17 }
18 
19 - (void)gotDataArray:(NSArray *)array {
20     if(array){
21 //        NSLog(@"array:%@",array);
22         dataArray = [array mutableCopy];
23         [myTableView reloadData];
24     }
25 }

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • var CalendarData=new Array(100); var madd=new Array(12); var tgString="甲乙丙丁戊己庚辛壬癸"; var dzString="子醜寅卯辰巳午未申酉戌亥"; var numString="一二三四五六七八九十"; var monSt
  • 具體可參考紅皮書第三版中的6.2.4章 書中的例題詳細講解了什麼是原型模式 function fop(){}; fop.prototype.name="xiaohong"; fop.prototype.age="12"; fop.prototype.sayName=function(){ conso
  • 閑聊:新年第一天上班,看著自己15年年底寫的代碼,真心覺得很爛,因為年底沒時間去寫,一想著做後臺管理需要獲取一周的開始和結束日期,就慌了,項目趕著測試呢,還有好多事情未做,就直接抄襲了網上的一段錯誤代碼,其實真的很簡單,今天重新花點時間封裝一下,以備後用,大神勿噴,謝謝! 一、封裝為jQuery版日
  • var numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411]; numbers = numbers.sort(function(){ return Math.random() – 0.5}); /* numbers 數組將類似於 [
  • function generateRandomAlphaNum(len) { var rdmString = ""; for( ; rdmString.length < len; rdmString += Math.random().toString(36).substr(2));return rd
  • 文檔對象模型DOM(Document Object Model)定義訪問和處理HTML文檔的標準方法。 DOM 將HTML文檔呈現為帶有元素、屬性和文本的樹結構(節點樹)。 把上面的代碼拆分為Dom節點圖 如圖: 三種常見的DOM節點: 1.元素節點: 比如:html、h2、p、ul、li 即標簽
  • iOS記憶體管理的方式是引用計數機制。分為MRC(人式引用計數)和ARC(自動引用計數)、 為什麼要學習記憶體管理? 記憶體管理方式是引用計數機制,通過控制對象的引用計數來實現操作對象的功能。一個對象的生命周期有生成,持有,釋放,銷毀。引用計數分為ARC,MRC,在MRC中,增加引用計數的方法是retai
  • android許可權大全轉http://www.cnblogs.com/classic/archive/2011/06/20/2085055.html
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...