문제

가를 분석해 확인된다.하지만 지금은 나가는 데 문제가 값 는 내가 필요합니다.를 얻을 수 있습의 요소 및 특성이 있습니다.하지만 얻을 수 없다.고 싶은 값을 얻을의 프레임에서 이 xml 그것은 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'
도움이 되었습니까?

해결책

국외 거주자는 매우 어렵습니다. 외국인은 요소의 내용이 아니라 구조에만 관심이있을 때 더 좋습니다. 사용하지 않는 이유는 무엇입니까? libxml 대신에? 트리 기반이 아닌 국외 파서와 같은 고른 파서를 사용한 이유는 무엇입니까?

어쨌든,이를 수행하는 방법은 문자 데이터 처리기를 설정하는 것입니다. 다음은 코드를 기반으로 한 예입니다.

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

다른 팁

The'value'20 는 문자 데이터"20"에서 요소의 이름이"항목을"그리고 그의 이름 특성은"프레임".

을 받을 문자 데이터 이벤트 콜백을 등록하으로 XML_SetCharacterDataHandler 기능입니다.

이러 콜백을 받을 것이 문자 데이터입니다.파서 분할할 수 있습는 문자 데이터-일반적으로 처리하의 끝에 도달하는 버퍼에 대한,또는 엔티티(도 foo&amp;bar 귀하의 처리기를 얻을 것이 세 호출-"foo","&"과"바"),그래서 당신이 문자열을 붙여 함께 부분을 다해야 하는 경우의 전체 데이터입니다.

당신이 알고 있을 때 모든 문자 데이터 내부에는 노드를 수신하면 다음 요소로 시작하거나 가까운 콜백입니다.

할 때 모든 문자 데이터 처리할 수 있습니다.

독립를 들어 단순화에서 당신의 코드:

#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;
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top