2017-02-01 78 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