之前在做的一个小项目,需要使用套接字发送xml,所以使用到了libxml这个库(基本用法在上一篇文章有说)。
在发送端监测的xml字符串明明还是正常的,到了接收端就各种收不全,不然就是收到了然后解析错误,查资料也没找到类似的问题,弄得神烦。
问题一:
Entity: line 1: parser error : XML declaration allowed only at the start of the document <?xml ve ^ Entity: line 1: parser error : Char 0x0 out of allowed range <?xml ve ^ Entity: line 1: parser error : Char 0x0 out of allowed range <?xml ve ^ Entity: line 1: parser error : ParsePI: PI xml never end ... <?xml ve ^ Entity: line 1: parser error : Start tag expected,'<' not found <?xml ve ^ read file error
这个问题是收不全。有两种可能性。
(一)原因在发送端。
发送端使用到一个函数:
xmlDocDumpFormatMemoryEnc(xmlDocPtr xDoc, &xmlChar * str, &int str_length,"utf8",1)
这个函数 是将生成好的xmlDocPtr变量中的xml转换为字符串存到str中,然后我们就可以将这个str通过write发送到接收端。这是基本原理。
但是!在write的时候我是这么写的:write(connect_fd,str,sizeof(str) );
于是就有了问题。这里sizeof(str)的长度是str这个指针的长度,等于4,而不是我们字符串的长度,所以导致了这个问题。
解决办法:改写为write(connect_fd,strlen(str)+1 );
注意最后要strlen(str)后面要+1,为了保证'\0'保持字符串完整。
(二)原因在接收端
接收端因为我使用的是epoll的边缘触发事件响应,所以需要while( recbytes > 0 ){ read( ); }这样来读取。
但是!在发送端,因为libxml的一些问题,xml字符串时候遇到空格,【write() read()】函数会将这个包断开,这就导致了出现接收到<?xml ve 这种不完整的字符串。
解决办法:在while( recbytes > 0 ){ read( ); }中添加拼接函数strncpy函数(之所以不用sprintf我会在下面说)
修改后的代码是这样:while( recbytes =read(connect_fd,buffer,MAXSIZE) ){ strncpy(str,sizeof(buffer) ); } return str;
这样将每次收到的字符串buffer拼接为str,即可。
问题二:
Entity: line 1: parser error : XML declaration allowed only at the start of the document <?xml version="1.0" encoding="utf8"?> ^ read file error
这个问题的成因在接收端。错误名: 只允许 在文档的开始进行 XML声明。
这个属于我误操作导致的。
这里我用到的拼接函数(拼接函数在上面的(二)原因在接收端提到)是sprintf(str,"%s%s",buffer)。
这个函数没有问题,问题在于我初始化字符串str时将其初始化为{' '},多了个空格。这样xml开头就是一个空格,而不是xml的声明,导致了这个错误。
解决办法:很简单,对str初始化为空,或者不对str初始化就行了。
原文链接:https://www.f2er.com/xml/298443.html