2017-02-01 23 views
12

में पूर्ण डाउनलोड के इंतजार किए बिना भाग में एक एक्सएमएल फ़ाइल को पार्स करें IOS में, मैं डाउनलोड करते समय सर्वर से एक्सएमएल स्ट्रीम को पार्स करना चाहता हूं। इसे तब तक इंतजार नहीं करना चाहिए जब तक सर्वर एक्सएमएल का निर्माण नहीं कर लेता है और डाउनलोड पूरा हो जाता है। सर्वर एक्सएमएल को "भाग" में बनाता है और इसे सीधे क्लाइंट को भेजता है। मेरे ऐप में मेरे पास UITableView है जो मुझे सर्वर से प्राप्त होने पर तुरंत XML के तत्वों को दिखाना चाहिए।स्विफ्ट

मैंने इसे XMLParser(contentsOf: URL) कन्स्ट्रक्टर के साथ आजमाया है, लेकिन यह पहले पूरे एक्सएमएल को डाउनलोड करता है और फिर इसे पार करता है। एक और कन्स्ट्रक्टर XMLParser(stream: InputStream) है, लेकिन मुझे नहीं पता कि InputStreamURLConnection से कैसे प्राप्त करें। मुझे मिली एकमात्र चीज this question थी जो लगभग 5 वर्ष पुरानी है, और मुझे यह समझ में नहीं आया कि स्विफ्ट 3 में यह कैसे किया जाए, अगर यह भी काम करता है।

दूसरी चीज जो मैंने कोशिश की थी वह Libxml2 के माध्यम से थी, लेकिन वहां मुझे राम उपयोग या अन्य चीजों के साथ समस्याएं हैं (मेरा old question देखें)।

मैं स्विफ्ट में पूर्ण डाउनलोड के इंतजार किए बिना भाग में एक्सएमएल स्ट्रीम कैसे पार्स कर सकता हूं?

एंड्रॉयड में, मैं एक 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

शायद क्लाइंट/सर्वर को कुछ सत्र-कुकीज़ के साथ कोई समस्या है? प्रत्येक अनुरोध के बाद उन्हें हटाने का प्रयास करें:

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

नीचे समाधान आपकी सहायता कर सकते हैं। मैंने आपके प्रश्न के बारे में पता लगाया है और नीचे दिए गए परिणाम के रूप में कुछ सफल हैं। लेकिन मैं एपीआई के नीचे समाधान की कमी की जांच करने में सक्षम नहीं हो सकता। अपने उपलब्ध एंडपॉइंट्स के साथ प्रयास करें। आशा है इससे आपकी मदद होगी।

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: //www.example.com/api/query.php? Title = test' – ElegyD

3

मूल रूप से दो प्रकार के पार्सर हैं: सैक्स और डोम। आपकी आवश्यकता के अनुसार, जहां आप XML तत्व प्राप्त होने के तुरंत बाद UITableView को अपडेट कर रहे हैं, यह बिल्कुल स्पष्ट है कि आपको केवल SAX पार्सर का उपयोग करना होगा। (डोम पार्सर ने पूरे दस्तावेज़ को पार्स किया और इन-मेमोरी प्रस्तुति का निर्माण किया जो आप विभिन्न तत्वों के लिए पूछ सकते हैं)। - iPhone SDK के साथ डिफ़ॉल्ट रूप से शामिल

1) NSXMLParser (यह XMLParser को नाम दिया गया है):

रूप में नीचे सूचीबद्ध iOS के लिए दो लोकप्रिय SAX पार्सर रहे हैं।

2) libxml2 - यह है कि के साथ डिफ़ॉल्ट रूप से शामिल किया गया है एक खुला स्रोत पुस्तकालय iPhone SDK

एप्पल एक उत्कृष्ट code नमूना कहा जाता XMLPerformance है कि आप समय यह एक ~ 900KB एक्सएमएल पार्स करने में लगने की तुलना कर सकते बना दिया है एनएसएक्सएमएल और libxml2 एपीआई दोनों के साथ शीर्ष 300 आईट्यून्स गाने युक्त दस्तावेज।

ठीक है, यहाँ एक ग्राफ कि पार्सर द्वारा शिखर स्मृति उपयोग

a busy cat

डाटा स्पष्ट रूप से दिखाता है (यह वस्तु आवंटन उपकरण के माध्यम से विभिन्न तरीकों से चल रहा है के माध्यम से प्राप्त किया गया था) से पता चलता है कि libxml2 के SAX विधि (जो आप पहले ही कोशिश कर चुके हैं) सबसे अच्छा विकल्प है जहां तक ​​चरम स्मृति उपयोग का संबंध है।

दूसरी ओर, XMLParser को लागू करना काफी आसान है। नीचे मेरा उदाहरण स्निपेट है जिसे मैंने इसका उपयोग करने की कोशिश की।

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

एक बार जब आप प्रतिनिधि, प्रतिनिधि विधियों के नीचे से प्रारंभ कहा जाता हो जाएगा के रूप में और जब:

अपनी कक्षा घोषणा में, XMLParserDelegate प्रोटोकॉल पार्सर प्रारंभ करने में विधि नीचे

class ViewController: UIViewController,XMLParserDelegate { 

override func viewDidLoad() { 
    super.viewDidLoad() 

उपयोग लागू आवश्यक:

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 (ContentOf: URL) कन्स्ट्रक्टर, लेकिन यह काम नहीं करता है। यह पहले वेबसाइट से पूरे एक्सएमएल डाउनलोड करता है और फिर इसे पार करता है। – ElegyD