The 'value' 20 is the character data "20" in the element whose tagname is "item" and whose name attribute is "frame".
To receive character data events, register a callback with the XML_SetCharacterDataHandler
function.
This callback will receive the character data. The parser may split character data - typically to handle reaching the end of a buffer, or for entities (so for foo&bar
your handler will get three calls - "foo", "&" and "bar"), so you have to paste the string parts together again if you need the whole of the data.
You know when you have all the character data inside a node when you receive the next element start or close callback.
When you have all the character data, you can process it.
A stand-alone example simplified from your code:
#include <expat.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
static const char* xml =
"<data>
"
" <header length="4">
"
" <item name="time" type="time">16</item>
"
" <item name="ref" type="string">3843747</item>
"
" <item name="port" type="int16">0</item>
"
" <item name="frame" type="int16">20</item>
"
" </header>
"
"</data>
";
void reset_char_data_buffer ();
void process_char_data_buffer ();
static bool grab_next_value;
void start_element(void *data, const char *element, const char **attribute) {
process_char_data_buffer();
reset_char_data_buffer();
if ( strcmp("item", element) == 0 ) {
size_t matched = 0;
for (size_t i = 0; attribute[i]; i += 2) {
if ( ( strcmp("name", attribute[i]) == 0 ) && ( strcmp("frame", attribute[i+1]) == 0 ) )
++matched;
if ( ( strcmp("type", attribute[i]) == 0 ) && ( strcmp("int16", attribute[i+1]) == 0 ) )
++matched;
}
if (matched == 2) {
printf("this is the element you are looking for
");
grab_next_value = true;
}
}
}
void end_element(void *data, const char *el) {
process_char_data_buffer();
reset_char_data_buffer();
}
static char char_data_buffer[1024];
static size_t offs;
static bool overflow;
void reset_char_data_buffer (void) {
offs = 0;
overflow = false;
grab_next_value = false;
}
// pastes parts of the node together
void char_data (void *userData, const XML_Char *s, int len) {
if (!overflow) {
if (len + offs >= sizeof(char_data_buffer) ) {
overflow = true;
} else {
memcpy(char_data_buffer + offs, s, len);
offs += len;
}
}
}
// if the element is the one we're after, convert the character data to
// an integer value
void process_char_data_buffer (void) {
if (offs > 0) {
char_data_buffer[ offs ] = '';
printf("character data: %s
", char_data_buffer);
if ( grab_next_value ) {
int value = atoi( char_data_buffer );
printf("the value is %d
", value);
}
}
}
int main (void ) {
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element, end_element);
XML_SetCharacterDataHandler(parser, char_data);
reset_char_data_buffer();
if (XML_Parse(parser, xml, strlen(xml), XML_TRUE) == XML_STATUS_ERROR)
printf("Error: %s
", XML_ErrorString(XML_GetErrorCode(parser)));
XML_ParserFree(parser);
return 0;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…