我设法解析好了。但现在我无法获得价值观 我需要的。我可以得到元素和属性。但无法获得价值。 我想在这个xml中得到frame的值为20。
/* track the current level in the xml tree */
static int depth = 0;
/* first when start element is encountered */
void start_element(void *data, const char *element, const char **attribute)
{
int i;
for(i = 0; i < depth; i++)
{
printf(" ");
}
printf("%s", element);
for(i = 0; attribute[i]; i += 2)
{
printf(" %s= '%s'", attribute[i], attribute[i + 1]);
}
printf("\n");
depth++;
}
/* decrement the current level of the tree */
void end_element(void *data, const char *el)
{
depth--;
}
int parse_xml(char *buff, size_t buff_size)
{
FILE *fp;
fp = fopen("start_indication.xml", "r");
if(fp == NULL)
{
printf("Failed to open file\n");
return 1;
}
XML_Parser parser = XML_ParserCreate(NULL);
int done;
XML_SetElementHandler(parser, start_element, end_element);
memset(buff, 0, buff_size);
printf("strlen(buff) before parsing: %d\n", strlen(buff));
size_t file_size = 0;
file_size = fread(buff, sizeof(char), buff_size, fp);
/* parse the xml */
if(XML_Parse(parser, buff, strlen(buff), XML_TRUE) == XML_STATUS_ERROR)
{
printf("Error: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
}
fclose(fp);
XML_ParserFree(parser);
return 0;
}
<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>
Output from parsing
Element: data
Element: header length= '4'
Element: item name= 'time' type= 'time'
Element: item name= 'ref' type= 'string'
Element: item name= 'port' type= 'int16'
Element: item name= 'frame' type= 'int16'
答案 0 :(得分:11)
外籍人士很难。当你只对结构感兴趣而不是元素的内容时,expat会更好。为什么不使用libxml呢?您使用基于均值的解析器(如expat)而不是基于树的解析器的原因是什么?
无论如何,这样做的方法是设置一个字符数据处理程序。以下是基于代码的示例:
#include <expat.h>
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 100000
/* track the current level in the xml tree */
static int depth = 0;
static char *last_content;
/* first when start element is encountered */
void
start_element(void *data, const char *element, const char **attribute)
{
int i;
for (i = 0; i < depth; i++) {
printf(" ");
}
printf("%s", element);
for (i = 0; attribute[i]; i += 2) {
printf(" %s= '%s'", attribute[i], attribute[i + 1]);
}
printf("\n");
depth++;
}
/* decrement the current level of the tree */
void
end_element(void *data, const char *el)
{
int i;
for (i = 0; i < depth; i++) {
printf(" ");
}
printf("Content of element %s was \"%s\"\n", el, last_content);
depth--;
}
void
handle_data(void *data, const char *content, int length)
{
char *tmp = malloc(length);
strncpy(tmp, content, length);
tmp[length] = '\0';
data = (void *) tmp;
last_content = tmp; /* TODO: concatenate the text nodes? */
}
int
parse_xml(char *buff, size_t buff_size)
{
FILE *fp;
fp = fopen("start_indication.xml", "r");
if (fp == NULL) {
printf("Failed to open file\n");
return 1;
}
XML_Parser parser = XML_ParserCreate(NULL);
XML_SetElementHandler(parser, start_element, end_element);
XML_SetCharacterDataHandler(parser, handle_data);
memset(buff, 0, buff_size);
printf("strlen(buff) before parsing: %d\n", strlen(buff));
size_t file_size = 0;
file_size = fread(buff, sizeof(char), buff_size, fp);
/* parse the xml */
if (XML_Parse(parser, buff, strlen(buff), XML_TRUE) == XML_STATUS_ERROR) {
printf("Error: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
}
fclose(fp);
XML_ParserFree(parser);
return 0;
}
int
main(int argc, char **argv)
{
int result;
char buffer[BUFFER_SIZE];
result = parse_xml(buffer, BUFFER_SIZE);
printf("Result is %i\n", result);
return 0;
}
答案 1 :(得分:11)
'value'20是标记名为“item”且名称属性为“frame”的元素中的字符数据“20”。
要接收字符数据事件,请使用XML_SetCharacterDataHandler
函数注册回调。
此回调将接收字符数据。解析器可以拆分字符数据 - 通常用于处理缓冲区的末尾,或者用于实体(因此对于foo&bar
,处理程序将获得三个调用 - “foo”,“&amp;”和“bar”),所以如果需要整个数据,则必须再次将字符串部分粘贴在一起。
当您收到下一个元素开始或关闭回调时,您知道节点内是否包含所有字符数据。
当你拥有所有角色数据时,你可以处理它。
从代码中简化的独立示例:
#include <expat.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
static const char* xml =
"<data>\n"\
" <header length=\"4\">\n"\
" <item name=\"time\" type=\"time\">16</item>\n"\
" <item name=\"ref\" type=\"string\">3843747</item>\n"\
" <item name=\"port\" type=\"int16\">0</item>\n"\
" <item name=\"frame\" type=\"int16\">20</item>\n"\
" </header>\n"\
"</data>\n";
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\n");
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 ] = '\0';
printf("character data: %s\n", char_data_buffer);
if ( grab_next_value ) {
int value = atoi( char_data_buffer );
printf("the value is %d\n", 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\n", XML_ErrorString(XML_GetErrorCode(parser)));
XML_ParserFree(parser);
return 0;
}