I am working on a parser to get data from an XML file. I am using libxml2 to extract data. I am a not able to get the attributes from nodes. I only found nb_attributes
if you just want a single attribute, use xmlGetProp or xmlGetNsProp
I think joostk meant attribute->children, giving something like this:
xmlAttr* attribute = node->properties;
while(attribute)
{
xmlChar* value = xmlNodeListGetString(node->doc, attribute->children, 1);
//do something with value
xmlFree(value);
attribute = attribute->next;
}
See if that works for you.
I think I found why you only got 1 attribute (at least it happened to me).
The problem was that I read attributes for first node but next is a text node. Don't know why, but node->properties gives me a reference to a non-readable part of memory, so it crashed.
My solution was to check node type (element is 1)
I'm using a reader, so:
xmlTextReaderNodeType(reader)==1
The entire code you can get it from http://www.xmlsoft.org/examples/reader1.c and add this
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;
}
}
to line 50.
Try something like:
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);
}
The easiest way I found using libxml2 (through libxml++ in C++) was to use the eval_to_XXX
methods. They evaluate an XPath expression, so you need to use the @property
syntax.
For example:
std::string get_property(xmlpp::Node *const &node) {
return node->eval_to_string("@property")
}
If you use SAX method startElementNs(...), this function is what you are looking for:
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;
}
Usage:
char * value = getAttributeValue("atrName", attributes, nb_attributes);
// do your magic
free(value);