2017-02-01 115 views
12

在iOS中,我想在下載時解析服務器中的XML流。它不應該等到服務器完成構建XML並下載完成。服務器以「塊」形式構建XML並將其直接發送給客戶端。在我的應用程序中,我有一個UITableView,它應該在我從服務器收到XML時立即顯示XML的元素。解析XML文件,無需等待Swift中的完整下載

我試過用XMLParser(contentsOf: URL)構造函數,但是這首先下載整個XML然後解析它。還有另一個構造函數XMLParser(stream: InputStream),但我不知道如何從URLConnection獲得InputStream。我發現的唯一的東西是this question,它已經快5年了,我無法理解它如何在Swift 3中做到這一點,如果它能夠正常工作的話。

我試過的另一件事是通過Libxml2,但在那裏我有內存使用或其他事情的問題(請參閱我的old question)。

如何解析XML流而不必等待Swift中的完整下載?

在Android中,我會用一個XMLPullParser和有:

URL url = new URL(urlString); 
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
connection.setRequestMethod("GET"); 
connection.setDoInput(true); 
InputStream inputStream = connection.getInputStream(); 

XmlPullParserFactory xmlFactoryObject = XmlPullParserFactory.newInstance(); 
XmlPullParser pullParser = xmlFactoryObject.newPullParser(); 
pullParser.setInput(inputStream, null); 
// here comes the actual parsing 

回答

2

也許客戶端/服務器在某些Session-Cookies上有問題?嘗試刪除它們後,每個請求:

// Loops through each of the cookies and deletes them. 
let cookieStore = HTTPCookieStorage.shared 
for cookie in cookieStore.cookies ?? [] { 
    cookieStore.deleteCookie(cookie) 
} 
1

以下解決方案可以幫助你。我已經探索了你的問題,並取得了一些成果,結果如下。但我無法測試以下解決方案缺乏的API。嘗試使用可用的端點。希望它能幫助你。

func xmlStream() { 
     let task = 
      URLSession.shared.streamTask(withHostName: "chat.example.com", port: 5555)               
     task.readData(ofMinLength: 16384, maxLength: 65536, timeout: 30.0) { (data, eof, error) in 

      let parser = XMLParser(data: data!) 
      parser.delegate = self 
      if parser.parse() { 
       //print result 
      } 

     } 
     task.resume() 

    } 

//XML parser methods 

而且this可以指導你。

+0

我試過你的解決方案,但數據爲零。我應該使用什麼端口? 443的HTTPS?因爲我的端點使用HTTPS,所以這個URL看起來像這樣:'https://www.example.com/api/query.php?title = Test' – ElegyD

3

基本上有兩種類型的解析器:SAX和DOM。根據您的要求,在XML元素收到後立即更新UITableView,這是非常清楚的,您將不得不使用SAX解析器。 (DOM解析器解析整個文檔並構建一個可以查詢不同元素的內存中表示)。

有適用於iOS兩個流行的SAX解析器,列出如下:

1)的NSXMLParser(這已更名爲XMLParser的) - 默認的iPhone SDK包括在內。

2)libxml2的 - 是默認使用包括開源庫的iPhone SDK

蘋果已經取得了一個很好的code樣品稱爲XMLPerformance,可以讓你比較才能解析〜900KB XML的時間包含使用NSXML和libxml2 API的前300首iTunes歌曲的文檔。

好的,這是一個說明由解析器內存使用峯值

a busy cat

數據清楚地顯示(這是通過運行通過對象分配工具的各種方法獲得)的曲線圖的libxml2的SAX方法(這你已經嘗試過)是最好的選擇,就峯值內存使用而言。

另一方面,實現XMLParser非常簡單。以下是我嘗試使用它的示例代碼片段。

在你的類聲明,實現XMLParserDelegate協議如下方法

class ViewController: UIViewController,XMLParserDelegate { 

override func viewDidLoad() { 
    super.viewDidLoad() 

用於初始化解析器:

func xmlParser() 
{ 
    posts = [] 
    parser = XMLParser(contentsOf:(NSURL(string:"http://images.apple.com/main/rss/hotnews/hotnews.rss"))! as URL)! 
    parser.delegate = self 
    parser.parse() 
} 

一旦你初始化委託,下面委託方法將被調用到什麼時候需要:

func parserDidStartDocument(_ parser: XMLParser) { 
    print("started") 
} 

func parserDidEndDocument(_ parser: XMLParser) { 
    print("ended") 
} 

func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { 
    print("didEndElement") 
} 

func parser(_ parser: XMLParser, foundCharacters string: String) { 
    print("foundCharacters") 
} 

還有其他代表方法以及您可以根據您的要求調用。

+0

對不起,但我已經在我的問題中解釋過我已經嘗試過XMLParser(contentsOf:URL)構造函數,但它不起作用。它首先從網站下載整個XML,然後解析它。 – ElegyD