как извлечь данные из процедуры какао iPhone саксофон xml - PullRequest
1 голос
/ 14 апреля 2009

Я пытаюсь прочитать и проанализировать XML-документ в приложении для iPhone. Я начинаю синтаксический анализ, а затем использую метод переопределения:

   static void startElementSAX(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, 
                        int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes)

Затем я пытаюсь преобразовать атрибуты в строку с:

   NSString *str1 = [[NSString alloc] initWithCString:attributes encoding:NSUTF8StringEncoding];

Почему параметр атрибутов имеет два ** перед ним. И почему при попытке извлечь данные и преобразовать их в строку с приведенным выше кодом я получаю предупреждение:

передача аргумента 1 из 'initWithCString: encoding:' из несовместимого типа указателя.

Ответы [ 5 ]

3 голосов
/ 14 апреля 2009

В документации для обратного вызова начального элемента libxml указано, что указатель на массив содержит 5 значений для каждого атрибута (количество атрибутов возвращается в nb_attributes). Это означает, что каждое 5-е значение в массиве является новым элементом атрибута.

Пять пунктов для каждого атрибута:

  1. localname (имя атрибута)
  2. префикс (пространство имен атрибута)
  3. URI
  4. [начало] значения (указатель на начало строки xmlChar для значения)
  5. end [of value] (указатель на конец строка xmlChar для значения)

Итак, вам нужно пройтись по массиву, получить каждое значение из элементов для первого атрибута, а затем использовать указатель начального значения, чтобы получить строку xmlChar, которая равна length = end - start. Затем начните заново со следующего атрибута, пока не прочитаете значение nb_attributes.

Если у вас болит голова, я настоятельно рекомендую вам перейти на Apple NSXMLParser (для ссылки может потребоваться вход в систему или использовать эту ссылку NSXMLParser ). В этом случае вы получите атрибуты как NSDictionary. Чтобы извлечь из него все атрибуты, вы можете сделать следующее:

for (NSString *attributeName in [attributeDict allKeys]) {
    NSString *attributeValue = [attributeDict objectForKey:attributeName];
    // do something here with attributeName and attributeValue
}

Если у вас есть доступ к сайту разработчиков iPhone, посмотрите на пример SeismicXML .

1 голос
/ 08 августа 2009

Образец отличный, за исключением двух вещей:

  • вам нужно увеличить 'i' на 5 после каждого цикла, поскольку для каждого атрибута есть 5 элементов.
  • выполнение strlen () в начале и в конце стоит дорого; легче просто вычесть начало с конца

for (int i = 0; i < nb_attributes*5; i += 5) 
{
    const char *attr = (const char *)attributes[i];
    const char *begin = (const char *)attributes[i + 3];
    const char *end = (const char *)attributes[i + 4];
    int vlen = end - begin;
    char val[vlen + 1];
    strncpy(val, begin, vlen);
    val[vlen] = '\0';
    NSLog(@"attribute %s = '%s'", attr, val);
}
1 голос
/ 21 июня 2009

Объяснение принятых ответов правильное, но полезно также посмотреть пример кода. Вот только один способ извлечь значение из атрибутов, по крайней мере, это работает, когда я проверял это. Я далеко не гуру С, хотя.

for (int i = 0; i < nb_attributes; i += 5) {
    const char *attr = (const char *)attributes[i];
    const char *begin = (const char *)attributes[i + 3];
    const char *end = (const char *)attributes[i + 4];
    int vlen = strlen(begin) - strlen(end);
    char val[vlen + 1];
    strncpy(val, begin, vlen);
    val[vlen] = '\0';
    NSLog(@"attribute %s: %d = %s", attr, i, val);
}

NSXMLParser - это хорошо, но, насколько я могу судить, он загружает весь XML перед обработкой. Используя libxml, он может читать порциями за раз. Это обеспечивает большую гибкость, но более высокую кривую обучения.

0 голосов
/ 14 апреля 2009

const xmlChar **namespaces - это массив CStrings (int nb_namespaces сообщает вам, сколько). Если вы хотите, чтобы каждое пространство имен представляло собой строку NSString, вы могли бы сделать что-то вроде следующего:

NSMutableArray *namespaces = [[NSMutableArray alloc] init];

int i;
for (i = 0; i < nb_namespaces; i++) {
    NSString *namespace = [[NSString alloc] initWithCString:attributes[i] encoding:NSUTF8StringEncoding];
    [namespaces addObject:namespace];
}

Метод initWithCString ожидает xmlChar *, который является указателем на xmlChar (первый символ в CString).

xmlChar ** означает указатель на указатель на xmlChar (первый символ в first CString).

0 голосов
/ 14 апреля 2009

Обозначение '**' означает «указатель на указатель». В C / C ++ «строка» представлена ​​массивом символов. Массив на самом деле является просто указателем под оболочкой, поэтому строку в C / C ++ можно объявить как char [] или char *. Нотация [] компилируется в указатель на массив.

Типичным примером этого является типичная "основная" функция в C / C ++:

int main(int argc, char **argv)

Что эквивалентно:

int main(int argc, char *argv[])

argv - это массив char * "строк" (аргументы командной строки для программы).

В данный момент я не могу привести пример, но, похоже, вам нужно перебирать атрибуты для доступа к отдельным строкам. Например, атрибуты [0] будут первой строкой атрибута (xmlChar *). Вы должны быть в состоянии преобразовать каждый отдельный атрибут в строку NSString.

...