Разобрать xml в Xcode с помощью Hpple

У меня есть xml, который выглядит так:

<menu>
    <day name="monday">
        <meal name="BREAKFAST">
            <counter name="Bread">
                <dish>
                    <name>Plain Bagel
                        <info name="Plain Bagel">
                            <serving>1 Serving (90g)</serving>
                            <calories>200</calories>
                            <caloriesFromFat>50</caloriesFromFat>
                        </info>
                    </name>
                </dish>
                <dish>
                    <name>Applesauce Coffee Cake
                        <info name="Applesauce Coffee Cake">
                            <serving>1 Slice-Cut 12 (121g)</serving>
                            <calories>374</calories>
                            <caloriesFromFat>104</caloriesFromFat>
                        </info>
                    </name>
                </dish>
            </counter>
        </meal>
    </day>
</menu>

И теперь я пытаюсь получить количество тегов под тегом info, которых должно быть три для первого тега info с атрибутом Plain Bagel.

Как я уже сказал, я использую парсер Hpple для iOS. Вот что у меня есть, и я пытаюсь, но не могу заставить его работать.

- (void)getData:(NSData*)factData {
    TFHpple *Parser = [TFHpple hppleWithHTMLData:factData];
    NSString *XpathQueryString = @"//day[@name='monday']/meal[@name='BREAKFAST']/counter[@name='Bread']/dish/name/info[@name='Plain Bagel']";
    NSArray *Nodes = [Parser searchWithXPathQuery:XpathQueryString];
    NSInteger count = Nodes.count;
    NSLog(@"count: %ld", count);
    for (TFHppleElement *element in Nodes) {
        NSLog(@"count inside: %ld", element.children.count);
    }
}

И первый счет дает 1. Это правильно, но внутренний счет дает 7, и здесь я запутался. И не уверен, почему это происходит. После того, как я попаду внутрь тега info, я хочу просмотреть каждый тег, порцию, калории и калории из жира и получить текст каждого тега. Но я не уверен, почему он дает 7?

Спасибо за помощь заранее.


person iqueqiorio    schedule 01.03.2015    source источник
comment
Используйте RaptureXML. Это очень простой и лучший парсер XML.   -  person Sam B    schedule 01.03.2015


Ответы (1)


Проблема в том, что вы используете синтаксический анализатор HTML, а не синтаксический анализатор XML. С точки зрения HTML у вас есть семь элементов между открытым и закрытым тегами info:

  • некоторый текст (новая строка и пробелы)
  • serving тег
  • некоторый текст (новая строка и пробелы)
  • calories тег
  • некоторый текст (новая строка и пробелы)
  • caloriesFromFat тег
  • некоторый текст (новая строка и пробелы)

Если вы выполните итерацию по объектам children, вы увидите именно это.

Если вам нужны только записи, связанные с тегами, вы можете проверить, есть ли у узла собственные дочерние элементы:

TFHpple *parser = [TFHpple hppleWithXMLData:factData];
NSString *xpathQueryString = @"//day[@name='monday']/meal[@name='BREAKFAST']/counter[@name='Bread']/dish/name/info[@name='Plain Bagel']";
NSArray *nodes = [parser searchWithXPathQuery:xpathQueryString];
for (TFHppleElement *element in nodes) {
    for (TFHppleElement *child in element.children) {
        if (child.children.count > 0) {  // see if the child, itself, has children
            NSLog(@"  %@: '%@'", child.tagName, child.content);
        }
    }
}

Или вы можете использовать предикат:

TFHpple *parser = [TFHpple hppleWithXMLData:factData];
NSString *xpathQueryString = @"//day[@name='monday']/meal[@name='BREAKFAST']/counter[@name='Bread']/dish/name/info[@name='Plain Bagel']";
NSArray *nodes = [parser searchWithXPathQuery:xpathQueryString];
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(TFHppleElement *node, NSDictionary *bindings) {
    return node.children.count > 0;
}];
for (TFHppleElement *element in nodes) {
    NSArray *filteredNodes = [element.children filteredArrayUsingPredicate:predicate];
    for (TFHppleElement *child in filteredNodes) {
        NSLog(@"  %@: '%@'", child.tagName, child.content);
    }
}

Если бы вы использовали правильный синтаксический анализатор XML (например, NSXMLParser), вы бы не имели дело со случайными символами между тегами open и close.

person Rob    schedule 01.03.2015
comment
Спасибо, есть ли способ удалить символы новой строки и пробелы, прежде чем я их проанализирую? - person iqueqiorio; 01.03.2015
comment
Я собирался сделать что-то вроде if (element != nil) {, а затем NSLog внутри и посмотреть, записался ли он 3 раза, но все же сделал 7, как я могу проверить, является ли этот элемент \n - person iqueqiorio; 01.03.2015
comment
Вы можете либо посмотреть на tagName, либо на количество его дочерних элементов (я сделал последнее выше). Откровенно говоря, я бы вообще не стал использовать Hpple, а скорее использовал бы NSXMLParser. - person Rob; 02.03.2015