2009-07-07 19 views
6

Estoy trabajando en un analizador para obtener datos de un archivo XML. Estoy usando libxml2 para extraer datos. No soy capaz de obtener los atributos de los nodos. Solo encontré nb_attributes para obtener el recuento de los atributos.Cómo obtener atributos de un nodo en libxml2

Respuesta

1

Pruebe algo como:

xmlNodePtr node; // Some node 
NSMutableArray *attributes = [NSMutableArray array]; 

for(xmlAttrPtr attribute = node->properties; attribute != NULL; attribute = attribute->next){ 
    xmlChar *content = xmlNodeListGetString(node->doc, attribute->children, YES); 
    [attributes addObject:[NSString stringWithUTF8String:content]]; 
    xmlFree(content); 
} 
+0

Hola Mat. Encontré tu código útil para descubrir los valores de atributo. Pero da el valor solo para el primer nodo. Cómo obtener valores para los siguientes nodos también. ??.. Gracias por adelantado. – NiKKi

+0

¿No debería 'node-children' convertirse en' attribute-> children'? –

+0

Sí, debería :) También vea @Matthew Lowe, notó el error antes. He actualizado la respuesta (2.5 años después;)) – Joost

8

Creo joostk significaba atributo-> niños, dando algo como esto:

xmlAttr* attribute = node->properties; 
while(attribute) 
{ 
    xmlChar* value = xmlNodeListGetString(node->doc, attribute->children, 1); 
    //do something with value 
    xmlFree(value); 
    attribute = attribute->next; 
} 

ver si funciona para usted.

+0

Hola Mat. Encontré tu código útil para descubrir los valores de atributo. Pero da el valor solo para el primer nodo. Cómo obtener valores para los siguientes nodos también. ??.. Gracias por adelantado. – NiKKi

+0

Puede iterar sobre nodos del mismo modo que itera sobre los atributos: node = node-> next. –

2

Creo que he encontrado por la que solo recibió 1 atributo (por lo menos a mi me pasó).

El problema es que leo los atributos para el primer nodo pero a continuación aparece un nodo de texto. No sé por qué, pero node-> properties me da una referencia a una parte no legible de la memoria, por lo que se colgó.

Mi solución fue la de comprobar el tipo de nodo (elemento es 1)

estoy usando un lector, por lo que:

xmlTextReaderNodeType(reader)==1 

El código completo se puede obtener de http://www.xmlsoft.org/examples/reader1.c y añadir esta

xmlNodePtr node= xmlTextReaderCurrentNode(reader); 
if (xmlTextReaderNodeType(reader)==1 && node && node->properties) { 
    xmlAttr* attribute = node->properties; 
    while(attribute && attribute->name && attribute->children) 
    { 
     xmlChar* value = xmlNodeListGetString(node->doc, attribute->children, 1); 
     printf ("Atributo %s: %s\n",attribute->name, value); 
     xmlFree(value); 
     attribute = attribute->next; 
    } 
} 

a la línea 50.

0

Si utiliza el método SAX startElementNs (...), esta función es lo que busca:

xmlChar *getAttributeValue(char *name, const xmlChar ** attributes, 
      int nb_attributes) 
{ 
int i; 
const int fields = 5; /* (localname/prefix/URI/value/end) */ 
xmlChar *value; 
size_t size; 
for (i = 0; i < nb_attributes; i++) { 
    const xmlChar *localname = attributes[i * fields + 0]; 
    const xmlChar *prefix = attributes[i * fields + 1]; 
    const xmlChar *URI = attributes[i * fields + 2]; 
    const xmlChar *value_start = attributes[i * fields + 3]; 
    const xmlChar *value_end = attributes[i * fields + 4]; 
    if (strcmp((char *)localname, name)) 
     continue; 
    size = value_end - value_start; 
    value = (xmlChar *) malloc(sizeof(xmlChar) * size + 1); 
    memcpy(value, value_start, size); 
    value[size] = '\0'; 
    return value; 
} 
return NULL; 
} 

Uso:

char * value = getAttributeValue("atrName", attributes, nb_attributes); 
// do your magic 
free(value); 
0

La forma más sencilla que encontré usando libxml2 (a través de libxml ++ en C++) era utilizar los métodos eval_to_XXX. Evalúan una expresión XPath, por lo que debe usar la sintaxis @property.

Por ejemplo:

std::string get_property(xmlpp::Node *const &node) { 
    return node->eval_to_string("@property") 
} 
+0

La forma más eficiente y directa con libxml ++ es 'return std :: string (dynamic_cast (node) -> get_attribute_value (" property "))'. Además, su declaración de parámetro es extraña: declara 'node' como una referencia a un puntero const para no const' xmlpp :: Node'. Más útil sería: 'const xmlpp :: Node * node' – maxschlepzig

Cuestiones relacionadas