Лучший подход для разбора XML на iPhone - PullRequest
5 голосов
/ 09 мая 2009

Я ознакомился с NSXMLParser из iPhone SDK, но я считаю, что управляемый событиями характер его неудобен для моих целей. Я просто хочу извлечь некоторые значения элементов, но эта концепция необходимости обрабатывать startElement, foundCharacters и endElement кажется более трудоемкой, чем она должна быть на самом деле. Я просто смотрю на это неправильно или есть более простой способ работы с XML с помощью дерева / DOM в iPhone SDK?

Если совет заключается в том, чтобы просто работать с NSXMLParser, существуют ли определенные шаблоны проектирования, которые я могу использовать, чтобы в моем коде не было 5 уровней вложенных if в методе startElement?

Ответы [ 3 ]

10 голосов
/ 09 мая 2009

Если вы работаете на iPhone, использование синтаксического анализа на основе дерева может стать препятствием для использования памяти. Поверьте мне, я был там, и я пробовал много разных подходов в течение последних пяти месяцев разработки моего основного приложения для iPhone. Синтаксический анализ на основе дерева работает нормально до тех пор, пока вы не загрузите чей-то поток комментариев, содержащий 400 очень длинных комментариев, с тактовой частотой около 600 КБ необработанных данных. Несмотря на размер результирующего дерева XML, память, выделяемая внутри при создании этого дерева, может быть огромной.

Я закончил создание варианта NSXMLParser, который извлекает данные из предоставленного NSInputStream, а не использует один кусок данных, и который передает только 1 КБ за раз в libxml для обработки (NSXMLParser также использует libxml, но передает 100% данных на одном дыхании).

Исходный код доступен на github (смотрите в папке StreamingXMLParser). Вы также найдете там суперкласс делегата; для большинства нужд анализа вы можете создать подкласс AQXMLParserDelegate и реализовать -start[Element]WithAttributes: (NSDictionary *) attrs и -end[Element] в своем подклассе. Эти методы будут вызываться для вас при обнаружении начальных и конечных тегов, а внутри конечного тега вы можете использовать self.characters для доступа к символам содержимого или CDATA элемента.

Дополнительные сведения об относительных объемах памяти различных анализаторов (хотя и на Mac, а не на iPhone) см. В моем исходном сообщении в блоге здесь и в продолжении NSXMLDocument здесь .

1 голос
/ 09 мая 2009

Рассмотрим следующий фрагмент кода, в котором используются libxml2 , Оболочки libxml2 Мэтта Галлахера и ASIHTTPRequest * * * Бен Бесси Копси для анализа XML-документа.

Экземпляр nodes типа NSArray* будет содержать 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 голосов
/ 09 мая 2009

Использование кода из Seismic XML обеспечивает очень хороший API, который создает подклассы NSObject из XML.

Если совет заключается в том, чтобы просто работать с NSXMLParser, существуют ли определенные шаблоны проектирования, которые я могу использовать, чтобы в моем коде не было 5 уровней вложенных if в методе startElement?

Я зависит от того, что ты пытаешься сделать. Вы можете поместить имена своих элементов в словарь и выполнить действие на основе соответствующего объекта в словаре - это фактически то, что делает SeismicXML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...