在C中拆分xml文本

时间:2011-07-22 04:46:54

标签: c parsing

这对我来说已经很久了......

好的,这就是我的目标:读入XML文本文件,将每个单词和标签分成数组中的自己的行。

例如,如果我将此文本输入我的程序:

<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

我会得到这个:

<note>
<to>
Tove
</to>
<from>
...

现在我的代码可以成功地执行此操作,但只能使用以下单词而不是上面的列表:

note
to
Tove
...

我想保留标签,否则我无法用它做我想做的事。所以我一直试图让它也添加标签,但一直都失败了

好的,这是我的代码:

//While the file is not empty
while(fgets(buffer, sizeof(buffer), stdin) != NULL){
    int first = 0;
    int last = 0;

    //While words are left in line
    while(last < INITIAL_SIZE && buffer[last] != '\0'){
        int bool = 0;
        //Tag detected
        if(buffer[last] == '<'){
            while(buffer[last] != '>'){
                last++;
            }

            bool = 1;
        }else{
            //While more chars are in the word
            while(last < INITIAL_SIZE && isalpha(buffer[last])){
                last++;
            }
        }
        //Word detected
        if(first < last){
            //Words array is full, add more space
            if(numOfWords == sizeOfWords){
                sizeOfWords = sizeOfWords + 10;
                words = (char **) realloc(words, sizeOfWords*sizeof(char *));
            }               
            //Allocate memory for array
            words[numOfWords] = (char *) calloc(last-first+1, sizeof(char));


            for(i = 0; i < (last-first); i++){
                words[numOfWords][i] = buffer[first + i];
            }
            //Add terminator to "new word"
            words[numOfWords][i] = '\0';
            numOfWords++;   
        }           
        //Move "Array Pointers" accordingly
            last++;
            first = last;
    }       
}

任何人都有任何想法,上面的代码是打印输出:

<note
<to
Tove
to 
<from
Jani
from
<heading
...
Don
t
forget
me
this
weekend
</body
</note

所以在这篇文章之后,有没有人知道我如何修改我当前的代码才能使其工作?或者其他人有其他选择吗?任何建议或帮助表示赞赏。

4 个答案:

答案 0 :(得分:0)

我的基本思维方式是:

first是当前单词中包含的第一个字母;

last是当前单词中第一个未包含的字母。

在您的程序中,当您检测到代码时,您不会包含>。此外,最后不需要last++,因为正在解析单词,一旦包含>,它就没用了。此外,您忘记不仅要检查\0作为字符串的结尾,还要检查\n作为行尾。

这是我的解决方案:

while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
    int first = 0;
    int last = 0;

    //While words are left in line
    while (last < INITIAL_SIZE && buffer[last] != '\0' 
          && buffer[last] != '\n')  { // <--------- Add this
        int Bool = 0;
        //Tag detected
        if (buffer[last] == '<') {
            while (buffer[last] != '>') {
                last++;
            }

            last++; // <--------- This
            Bool = 1;
        } else {
            //While more chars are in the word
            while (last < INITIAL_SIZE && isalpha(buffer[last])) {
                last++;
            }
        }
        //Word detected
        if (first < last) {
            //Words array is full, add more space
            if (numOfWords == sizeOfWords) {
                sizeOfWords = sizeOfWords + 10;
                words = (char **) realloc(words,
                        sizeOfWords * sizeof(char *));
            }
            //Allocate memory for array
            words[numOfWords] = (char *) calloc(last - first + 1,
                    sizeof(char));

            for (i = 0; i < (last - first); i++) {
                words[numOfWords][i] = buffer[first + i];
            }
            //Add terminator to "new word"
            words[numOfWords][i] = '\0';
            numOfWords++;
        }
        //Move "Array Pointers" accordingly
        first = last; // <--------- And change this
    }
}

答案 1 :(得分:0)

尽管任何人都会使用它是非常值得怀疑的,但我使用布尔类型逻辑让它工作。

while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
    int first = 0;
    int last = 0;

    //While words are left in line
    while (last < INITIAL_SIZE && buffer[last] != '\0' && buffer[last] != '\n'){
        int Bool = 0;
        //Tag detected
        if (buffer[last] == '<'){
            while (buffer[last] != '>')
                last++;
            Bool = 1;
        }else
            //While more chars are in the word
            while(last < INITIAL_SIZE && !isspace(buffer[last]) && buffer[last] != '<')
                last++;

        //Word detected
        if (first < last) {
            //Words array is full, add more space
            if (numOfWords == sizeOfWords) {
                sizeOfWords = sizeOfWords + 10;
                words = (char **) realloc(words, sizeOfWords * sizeof(char *));
            }
            //Allocate memory for array
            words[numOfWords] = (char *) calloc(last - first + 1, sizeof(char));

            int xHolder = 0;
            if(buffer[first] == '/'){
                words[numOfWords][0] = '<';
                xHolder++;
                Bool++;
            }
            for (i = 0; i < (last - first + Bool); i++) {
                words[numOfWords][xHolder] = buffer[first + i];
                xHolder++;
            }
            //Add terminator to "new word"
            words[numOfWords][i] = '\0';
            numOfWords++;
        }
        //Move "Array Pointers" accordingly
        last++;
        first = last;
    }
}

答案 2 :(得分:0)

我在这里给出的最好的建议是当我在comp.lang.c上发布this时给我的。

<强>功能

几乎无处不在,你写了一个全行注释,注释中的重要单词应该是当时调用的函数的名称。

ProcessFile
    while(fgets..)
        ProcessWords()

ProcessWords
    if(DetectTag)
        ...

以这种方式重构使得复杂的代码更容易阅读(对你而言)。它允许您的顶级逻辑读取像伪代码一样,而所有的虚拟位都可以组合在一起。也许有一天,标签将使用花括号。将您的文字放在#define s甚至enums中。这样,以后可以轻松地进行简单的语法更改。

目标是你能够同时在屏幕上看到整个功能体。这允许您分别验证每个部分。

答案 3 :(得分:-1)

你的内循环可能有问题