且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

歌厅使用XML解析器外籍XML数据

更新时间:2023-11-24 21:01:16

这与外籍人士相当困难的。外籍较好时只与结构,而不是元素的含量感兴趣。为什么不使用的libxml 呢?你有什么理由使用像外籍人士甚至基于解析器,而不是基于树的一个?

总之,要做到这一点的方法是设置字符数据处理程序。下面是一个例子,根据您的code:

 的#include< expat.h>
#包括LT&;&stdio.h中GT;
#包括LT&;&string.h中GT;的#define BUFFER_SIZE 100000/ *追踪XML树当前等级* /
静态INT深度= 0;静态字符* last_content;/ *遇到开始元素时首先* /
空虚
START_ELEMENT(void *的数据,为const char *元素,为const char **属性)
{
    INT I;    对于(i = 0; I<深度;我++){
        的printf();
    }    的printf(%S,部件);    为(ⅰ= 0;属性由[i]; I + = 2){
        的printf(%s =%s的属性[I],属性[I + 1]);
    }    的printf(\\ n);
    深入++;
}/ *递减树的当前级别* /
空虚
END_ELEMENT(void *的数据,为const char * EL)
{
    INT I;
    对于(i = 0; I<深度;我++){
        的printf();
    }
    的printf(元素的含量(%)S为\\%s \\的\\ n,EL,last_content);
    深度 - ;
}空虚
handle_data(void *的数据,为const char *的内容,INT长度)
{
    字符* TMP =的malloc(长度);
    函数strncpy(TMP,内容长度);
    TMP [长度] ='\\ 0';
    数据=(无效*)tmp目录;
    last_content = tmp目录; / * TODO:串联文本节点? * /
}INT
parse_xml(字符* BUFF,为size_t BUFF_SIZE)
{
    FILE * FP;
    FP = FOPEN(start_indication.xml,R);
    如果(FP == NULL){
        的printf(无法打开文件\\ n);
        返回1;
    }    XML_Parser解析器= XML_ParserCreate(NULL);
    XML_SetElementHandler(分析器,START_ELEMENT,END_ELEMENT);
    XML_SetCharacterDataHandler(分析器,handle_data);    memset的(BUFF,0,BUFF_SIZE);
    的printf(strlen的(BUFF)分析之前数:%d \\ n,strlen的(BUFF));    为size_t FILE_SIZE = 0;
    FILE_SIZE = FREAD(BUFF,sizeof的(炭),BUFF_SIZE,FP);    / *解析XML * /
    如果(XML_Parse(分析器,浅黄色,strlen的(BUFF),XML_TRUE)== XML_STATUS_ERROR){
        的printf(错误:%s \\ n,XML_ErrorString(XML_GetError code(分析器)));
    }    FCLOSE(FP);
    XML_ParserFree(分析器);    返回0;
}INT
主(INT ARGC,字符** argv的)
{
    INT结果;
    字符缓冲区[BUFFER_SIZE];
    结果= parse_xml(缓冲,BUFFER_SIZE);
    的printf(结果是%I \\ N,结果);
    返回0;
}

I have managed to parse ok. But now I am having trouble getting the values that I need. I can get the element and the attributes. But cannot get the values. I would like to get the value of frame in this xml it is 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'

It is quite difficult with expat. expat is better when you are only interested with the structure, not the content of the elements. Why not using libxml instead? What are your reasons for using an even-based parser like expat, rather than a tree-based one?

Anyway, the way to do it is to set a character data handler. Here is an example, based on your code:

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