c - Expat (C) - "invalid token"(几乎)每一行

标签 c xml xml-parsing expat-parser

我有一些 XML 试图用 C 中的 Expat 处理。XML 可以用 Java 解析,所以我没有理由相信它是格式错误的。此外,我拥有的 C 代码将解析我“手动”插入的字符串文字 - 但它无法解析我的 XML 文件。

这是代码(我添加了一些东西——如果上帝希望我们使用调试器,他就不会给我们 printf):

static void XMLCALL
starthandler(void *data, const XML_Char *name, const XML_Char **attr)
{
int i;
if (strcmp(name, "file") == 0) {
    for (i = 0; attr[i]; i += 2) {
        if (strcmp(attr[i], "path") == 0) {
            printf("File is at %s\n", attr[i + 1]);
        }
    }
}
}       

int main(int argc, char *argv[])
{
FILE* inXML;
ssize_t read;
char* line;
size_t len = 0;

XML_Parser p_ctrl = XML_ParserCreate("UTF-8");
if (!p_ctrl) {
    fprintf(stderr, "Could not create parser\n");
    exit(-1);
}

XML_SetStartElementHandler(p_ctrl, starthandler);
inXML = fopen(argv[1], "r");
if (inXML == NULL) {
    fprintf(stderr, "Could not open %s\n", argv[1]);
    XML_ParserFree(p_ctrl);
    exit(-1);
}

while ((read = getline(&line, &len, inXML)) != -1) {
    printf("Line is %s", line);
    enum XML_Status status = XML_Parse(p_ctrl, line, len, 0);
    if (status == 0) {
        enum XML_Error errcde = XML_GetErrorCode(p_ctrl);
        printf("ERROR: %s\n", XML_ErrorString(errcde));
        printf("Error at column number %lu\n",    XML_GetCurrentColumnNumber(p_ctrl));
        printf("Error at line number %lu\n", XML_GetCurrentLineNumber(p_ctrl));
    }
    free(line);
    line = NULL;
    len = 0;
}

XML_ParserFree(p_ctrl);
fclose(inXML);
return 0;
} 

这是我试图解析的 XML 文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE threadrecordml [
<!ELEMENT threadrecordml (file)*>
<!ATTLIST threadrecordml version CDATA #FIXED "0.1">
<!ATTLIST threadrecordml xmlns CDATA #FIXED "http://cartesianproduct.wordpress.com">
<!ELEMENT file EMPTY>
<!ATTLIST file thread CDATA #REQUIRED>
<!ATTLIST file path CDATA #REQUIRED>
]>
<threadrecordml xmlns="http://cartesianproduct.wordpress.com">
<file thread="1" path="tester_1.xml" />
<file thread="3" path="tester_3.xml" />
<file thread="2" path="tester_2.xml" />
<file thread="4" path="tester_4.xml" />
<file thread="5" path="tester_5.xml" />
<file thread="6" path="tester_6.xml" />
<file thread="7" path="tester_7.xml" />
<file thread="8" path="tester_8.xml" />
<file thread="9" path="tester_9.xml" />
<file thread="10" path="tester_10.xml" />
<file thread="11" path="tester_11.xml" />
<file thread="12" path="tester_12.xml" />
<file thread="13" path="tester_13.xml" />
<file thread="14" path="tester_14.xml" />
<file thread="15" path="tester_15.xml" />
<file thread="16" path="tester_16.xml" />
<file thread="17" path="tester_17.xml" />
<file thread="18" path="tester_18.xml" />
</threadrecordml>

这是输出示例...

adrianm@imola:/n/staffstore/adrianm/optGenC$ ./optgenc ../tester_control.xml 
Line is <?xml version="1.0" encoding="UTF-8" standalone="no"?>
ERROR: not well-formed (invalid token)
Error at column number 0
Error at line number 2
Line is <!DOCTYPE threadrecordml [
ERROR: not well-formed (invalid token)
Error at column number 0
Error at line number 3
Line is <!ELEMENT threadrecordml (file)*>
ERROR: not well-formed (invalid token)
Error at column number 0
Error at line number 4
Line is <!ATTLIST threadrecordml version CDATA #FIXED "0.1">
ERROR: not well-formed (invalid token)
Error at column number 0

(对于所有行)

如果我“作弊”并在读取后添加这一行...

line = "<file thread=\"1\" path=\"tester.xml\" />";

该行将被解析(代码当然会因其他原因中断)。

所以在从磁盘文件读取时似乎发生了一些损坏...这可能是作为 16 位读取的吗?但是将解析器的编码更改为 NULL 或 UTF-16 似乎没有任何区别。

谁能解释一下? (如果有什么不同的话,我已经在 64 位 OSX 和 Linux 机器上运行了这段代码并且遇到了同样的问题)

最佳答案

答案是 getline(...) 在换行符后添加一个空字符,然后将其传递给解析器,但当然它不是有效的 XML,所以它会导致失败 - 因为它在换行符之后,这被记录为第 2 行,依此类推。

这样做可以解决问题:

do {
    len = fread(data, 1, sizeof(data), inXML);
    done = len < sizeof(data);

    if (XML_Parse(p_ctrl, data, len, 0) == 0) {
        enum XML_Error errcde = XML_GetErrorCode(p_ctrl);
        printf("ERROR: %s\n", XML_ErrorString(errcde));
        printf("Error at column number %lu\n", XML_GetCurrentColumnNumber(p_ctrl));
        printf("Error at line number %lu\n", XML_GetCurrentLineNumber(p_ctrl));
    }
} while(!done);

关于c - Expat (C) - "invalid token"(几乎)每一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21699234/

相关文章:

c - 一条一条地打印记录

c - C语言的家谱

xml - 通过匹配另一个节点名称来获取节点或通过匹配另一个节点来排除节点

xml - 斯卡拉 XML : test for node existence and value

c - 这个 C 语言的反向字符串函数写得不好吗?/如何使这段代码更好?

java - 即使我使用 AsyncTask 减轻主线程上的负载,应用程序也说没有响应

javascript - 缩略图库的 XML 数据图像绑定(bind)

python xml.etree.ElementTree 附加到子元素

Groovy XML 和 "xml:"命名空间

c - 在游戏中移动敌人的简单问题 (C/SDL)