2009-05-08 4 views
5

पर एक्सएमएल पार्सिंग के लिए सर्वश्रेष्ठ दृष्टिकोण मैंने आईफोन एसडीके से एनएसएक्सएमएलपार्सर के साथ खुद को परिचित कर लिया है, लेकिन मुझे अपने उद्देश्यों के लिए घटना की प्रेरित प्रकृति को अजीब लगता है। मैं बस कुछ तत्व मान निकालना चाहता हूं लेकिन स्टार्ट एलिमेंट को संभालने की इस अवधारणा को मिला, खरीदार, और एंडलेमेंट वास्तव में ऐसा होना चाहिए जितना वास्तव में होना चाहिए। क्या मैं इसे गलत तरीके से देख रहा हूं या आईफोन एसडीके में एक्सएमएल के साथ काम करने का एक आसान पेड़/डोम-आधारित तरीका है?आईफोन

यदि सलाह केवल NSXMLParser के साथ काम करना है, तो क्या कुछ डिज़ाइन पैटर्न हैं जिनका उपयोग मैं अपने कोड को स्टार्ट एलीमेंट विधि में नेस्टेड ifs के 5 स्तरों से रखने के लिए उपयोग कर सकता हूं?

उत्तर

10

आप iPhone पर हैं, तो का उपयोग कर पेड़ आधारित पार्स एक निषेधात्मक स्मृति हॉग हो सकता है। मेरा विश्वास करो, मैं वहां गया हूं, और मैंने अपने मुख्य आईफोन एप्लिकेशन के विकास के पिछले पांच महीनों में कई अलग-अलग दृष्टिकोणों की कोशिश की है। वृक्ष-आधारित पार्सिंग तब तक ठीक काम करती है जब तक कि आप 400 की लंबी टिप्पणियों वाली किसी भी टिप्पणी स्ट्रीम को डाउनलोड न करें, कच्चे डेटा के लगभग 600 केबी पर घड़ी करें। परिणामी एक्सएमएल पेड़ के आकार से काफी अलग, उस पेड़ को बनाते समय आंतरिक रूप से आवंटित स्मृति बहुत बड़ी हो सकती है।

मैं जो बजाय डेटा का एक हिस्सा का उपयोग करने से एक की आपूर्ति की NSInputStream से में डेटा खींचती NSXMLParser का एक संस्करण बनाने को बंद कर, और जो से निपटने के लिए libxml में एक समय में केवल 1KB गुजरता (NSXMLParser भी libxml का उपयोग करता है, लेकिन एक बार में 100% डेटा पास करता है)।

स्रोत कोड on github उपलब्ध है (StreamingXMLParser फ़ोल्डर में देखें)। आपको वहां एक प्रतिनिधि सुपरक्लास भी मिलेगा; अधिकांश पार्सिंग जरूरतों के लिए आप AQXMLParserDelegate को उपclass कर सकते हैं और -start[Element]WithAttributes: (NSDictionary *) attrs और -end[Element] को अपने उप-वर्ग में कार्यान्वित कर सकते हैं। इन विधियों को आपके लिए बुलाया जाएगा क्योंकि स्टार्ट एंड एंड टैग की खोज की गई है, और अंत टैग के अंदर आप सामग्री वर्णों या तत्व के सीडीएटीए तक पहुंचने के लिए self.characters का उपयोग कर सकते हैं।

अलग पारसर्स के सापेक्ष स्मृति पैरों के निशान के बारे में अधिक (Mac पर, नहीं iPhone यद्यपि) के लिए अपने मूल ब्लॉग पोस्ट here और NSXMLDocument here पर फॉलोअप देखते हैं।

+0

धन्यवाद यह उपयोगी जानकारी है। मैंने स्टार्ट एलीमेंट को अपनाने का अंत किया, पाया गया कैरेक्टर, एंडलेमेंट पैटर्न और यह बहुत बुरा नहीं था लेकिन हाँ अब मैं देख रहा हूं कि NSXMLParser initWithContentsOfURL पूरे दस्तावेज़ को डाउनलोड करने लगता है और स्ट्रीमिंग के विपरीत इसे स्मृति में छोड़ देता है - जैसे आपने बताया। जो कि आश्चर्यजनक है क्योंकि जब आप किसी ईवेंट-आधारित पार्सिंग दृष्टिकोण का उपयोग कर रहे हों तो आपको पूरे दस्तावेज़ तक पहुंच की आवश्यकता नहीं है। मैं StreamingXMLParser में देखूंगा। – Marplesoft

+0

ठीक है और अधिक जांच। अब मैं देख रहा हूं कि वास्तविक पार्सिंग की तुलना में यूआरएल डाउनलोड के कारण मेमोरी पदचिह्न मोरेसो है। क्या मैं एसिंक डाउनलोड कर रहा हूं लेकिन ऐसा लगता है कि यह पहले से प्राप्त डेटा भाग जारी नहीं कर रहा है। – Marplesoft

+0

हाँ, एनएसआरएलकनेक्शन सामग्री चीजें करते समय आंतरिक रूप से मेमोरी का एक उचित बिट आवंटित करती है- और यदि आप एसएसएल का उपयोग कर रहे हैं तो एन्क्रिप्शन पाइपलाइन के लिए ~ 1 एमबी अतिरिक्त आवंटित किया गया है। मैंने CFHTTPMessageRef के आस-पास अपना स्वयं का रैपर लिखना और पार्सर को खिलाने के लिए स्ट्रीम प्राप्त करने के लिए इसका उपयोग किया; HTTP मैसेज सबफ़ोल्डर में, एक ही जिथब रिपोजिटरी में है। –

1

निम्न कोड स्निपेट पर विचार करें, जो libxml2, Matt Gallagher's libxml2 wrappers और Ben Copsey's ASIHTTPRequest का उपयोग किसी XML दस्तावेज़ को पार्स करने के लिए करता है।

प्रकार NSArray* की nodes उदाहरण NSDictionary* वस्तुओं है कि आप रिकर्सिवली पार्स डेटा आप चाहते हैं पाने के लिए कर सकते हैं शामिल होंगे।

या, यदि आप अपने XML दस्तावेज़ की योजना पता है, तुम एक XPath क्वेरी लिख सकते हैं तो आप सीधे एक nodeContent या nodeAttribute मूल्य को पाने के लिए।

ASIHTTPRequest *request = [ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://stackoverflow.com/"]; 
[request start]; 
NSError *error = [request error]; 
if (!error) { 
    NSData *response = [request responseData]; 
    NSLog(@"Root node: %@", [[self query:@"//" withResponse:response] description]); 
} 
else 
    @throw [NSException exceptionWithName:@"kHTTPRequestFailed" reason:@"Request failed!" userInfo:nil]; 
[request release]; 

... 

- (id) query:(NSString *)xpathQuery withResponse:(NSData *)respData { 
    NSArray *nodes = PerformXMLXPathQuery(respData, xpathQuery); 
    if (nodes != nil) 
     return nodes; 
    return nil; 
} 
0

सेस्मिक एक्सएमएल से कोड का पुनरुत्पादन एक बहुत अच्छा एपीआई प्रदान करता है जो एक्सएमएल से एनएसओब्जेक्ट सबक्लास बनाता है।

सलाह सिर्फ NSXMLParser के साथ काम करना है, तो वहाँ कुछ डिजाइन पैटर्न मैं startElement विधि में नेस्ट आईएफएस के 5 स्तरों होने से मेरी कोड रखने के लिए उपयोग कर सकते हैं कर रहे हैं?

मैं इस बात पर निर्भर करता हूं कि आप क्या करने की कोशिश कर रहे हैं।आप अपने तत्वों को एक शब्दकोश में डाल सकते हैं और एक शब्दकोश में प्रासंगिक वस्तु के आधार पर कार्रवाई कर सकते हैं - यह प्रभावी रूप से SeismicXML करता है।