Pergunta

Eu estou tentando ler e analisar um documento XML em um aplicativo para iPhone. Eu começar a analisar e, em seguida, usar o método de substituição:

   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)

Eu, então, tentar converter os atributos para uma string com:

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

Por que os atributos parâmetro tem duas ** na frente dele. E por que quando se tenta extrair os dados e convertê-lo para uma string com o código acima que eu recebo o aviso:

passando argumento de um 'initWithCString: que codifica:'. Do tipo de ponteiro incompatível

Outras dicas

A amostra é grande, exceto por duas coisas:

  • você precisa bater 'i' por 5 após cada ciclo uma vez que existem 5 itens para cada atributo.
  • Fazer strlen () em ambos começam e terminam é caro; é mais fácil basta subtrair começar a partir do final

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);
}

O respostas explicação aceita é correta, mas é útil para ver um exemplo de código também. Aqui é apenas uma maneira de extrair o valor dos atributos, pelo menos ele funciona quando eu testei. Estou longe de ser um guru C embora.

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 é agradável, mas pelo que eu posso dizer, ele faz o download de todo o XML antes do processamento. Usando libxml ele pode ler em pedaços de cada vez. Ele permite maior flexibilidade, mas maior curva de aprendizagem.

Os meios de notação '**' "ponteiro para um ponteiro." Em C / C ++, uma "cadeia" é representado por um conjunto de caracteres. Uma matriz é realmente apenas um ponteiro sob o cobre, por isso, uma cadeia em C / C ++ pode realmente ser declarado como seja "char []" ou "char *". O [] notação compila para baixo para um apontador para uma matriz.

Um exemplo comum é a função normal "principal" em C / C ++:

int main(int argc, char **argv)

O que é equivalente a:

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

argv é uma matriz de char * "strings" (os argumentos de linha de comando para o programa).

Eu não posso dar um exemplo, no momento, mas parece que você precisa iterar sobre atributos para acessar as cordas individuais. Por exemplo, os atributos [0] seria a primeira cadeia de atributo (um xmlChar *). Você deve ser capaz de converter cada atributo individual para um NSString.

const xmlChar **namespaces é uma matriz de CStrings (int nb_namespaces informa quantas). Se você deseja que cada namespace como um NSString, você poderia fazer algo como o seguinte:

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];
}

O método initWithCString espera xmlChar *, que é um ponteiro para uma xmlChar (o primeiro caractere em uma CString).

meios xmlChar ** apontador para um apontador para um xmlChar (o primeiro caractere no primeira CString).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top