借助libxml2库进行xml文件的读写,本篇记录读取文件
【libxml2算法库、头文件在这里下载】
这里需要处理的xml文件格式如下所示。其中,包含了“根节点”、“子节点”、“子节点属性(孙子节点)”;如有更深刻进一步修改复用。
<?xml version="1.0" encoding="utf-8"?>
<annotation>
<filename>5d648b8073497c9e9490b50bdc175a7_1003959936.jpg</filename>
<size>
<width>1920</width>
<height>1088</height>
<depth>3</depth>
</size>
<object>
<name>0</name>
<truncated>0</truncated>
<bndbox>
<xmin>832</xmin>
<ymin>336</ymin>
<xmax>1853</xmax>
<ymax>1008</ymax>
</bndbox>
</object>
<object>
<name>0</name>
<truncated>0</truncated>
<bndbox>
<xmin>111</xmin>
<ymin>222</ymin>
<xmax>333</xmax>
<ymax>444</ymax>
</bndbox>
</object>
</annotation>
通过以下代码,将xml文件中的所有数据读取出来
#include<libxml/parser.h>
#include<libxml/tree.h>
//定义size节点结构体
typedef struct size_node{
int width;
int height;
int depth;
}size_node;
//定义object节点结构体
typedef struct object_node{
int name;
int truncated;
int xmin;
int ymin;
int xmax;
int ymax;
}object_node;
//定义xml文件所有数据结构体
typedef struct xml_data{
string filename;
size_node size;
object_node objects[20];
int node_nums;
}xml_data;
/*function:将xml文件数据读取到xml_data类型的变量中*/
int parse_xml_struct_Data(string xml_path, xml_data* xml_info)
{
xmlDocPtr doc; //定义解析文档指针
xmlNodePtr curNode; //定义结点指针(你需要它为了在各个结点间移动)
xmlNodePtr curNode_chile;
xmlNodePtr curNode_chile_child;
//xmlChar* attr_value = NULL;
xmlChar *szKey; //临时字符串变量
char szDocName[500];
strcpy(szDocName, xml_path.c_str());
using std::string;
using std::cout;
using std::endl;
doc = xmlReadFile(szDocName, "UTF-8", XML_PARSE_RECOVER); //解析文件
if (NULL == doc)
{
//文档打开错误
return -1;
}
curNode = xmlDocGetRootElement(doc); //确定文档根元素
/*检查确认当前文档中包含内容*/
if (NULL == curNode)
{
//空得xml文件
xmlFreeDoc(doc);
return -2;
}
/*在这个例子中,我们需要确认文档是正确的类型。“annotation”是在这个示例中使用文档的根类型。*/
if (xmlStrcmp(curNode->name, BAD_CAST "annotation"))
{
//分析根元素失败
xmlFreeDoc(doc);
return -3;
}
curNode = curNode->xmlChildrenNode;
xmlNodePtr propNodePtr = curNode;
while (curNode != NULL)
{
//取出节点中的内容
if (xmlStrcmp(curNode->name, (const xmlChar *)"text") == 0)
{
curNode = curNode->next;
if (curNode == NULL)
{
break;
}
}
if (xmlStrcmp(curNode->name, (const xmlChar *)"filename") == 0)
{
szKey = xmlNodeGetContent(curNode);
//cout << szKey << endl; //得到node2的值并输出
char files[500];
sprintf(files, "%s", szKey);
xml_info->filename = string(files);
xmlFree(szKey);
}
else if (xmlStrcmp(curNode->name, (const xmlChar *)"size") == 0)
{
szKey = xmlNodeGetContent(curNode);
//cout << szKey << endl; //得到node2的值并输出
xmlFree(szKey);
curNode_chile = curNode->xmlChildrenNode;
//子节点的子节点没有遍历结束,就继续遍历
while (curNode_chile->next != NULL)
{
while (xmlStrcmp(curNode_chile->name, (const xmlChar *)"text") == 0)
{
curNode_chile = curNode_chile->next;
}
if (xmlStrcmp(curNode_chile->name, (const xmlChar *)"width") == 0)
{
szKey = xmlNodeGetContent(curNode_chile);
char * stream = (char*)szKey;
//cout << "width = " << szKey << endl; //得到node2的值并输出
xml_info->size.width = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile->name, (const xmlChar *)"height") == 0)
{
szKey = xmlNodeGetContent(curNode_chile);
//cout << "height = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
xml_info->size.height = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile->name, (const xmlChar *)"depth") == 0)
{
szKey = xmlNodeGetContent(curNode_chile);
//cout << "depth = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
xml_info->size.depth = atoi(stream);
xmlFree(szKey);
}
curNode_chile = curNode_chile->next;
}
}
else if (xmlStrcmp(curNode->name, (const xmlChar *)"object") == 0)
{
//szKey = xmlNodeGetContent(curNode);
//cout << szKey << endl; //得到node2的值并输出
//xmlFree(szKey);
object_node* obj_tmp = &(xml_info->objects[xml_info->node_nums]);
curNode_chile = curNode->xmlChildrenNode;
while (curNode_chile->next != NULL)
{
while (xmlStrcmp(curNode_chile->name, (const xmlChar *)"text") == 0)
{
curNode_chile = curNode_chile->next;
}
if (xmlStrcmp(curNode_chile->name, (const xmlChar *)"name") == 0)
{
szKey = xmlNodeGetContent(curNode_chile);
//cout << "name = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
obj_tmp->name = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile->name, (const xmlChar *)"truncated") == 0)
{
szKey = xmlNodeGetContent(curNode_chile);
//cout << "truncated = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
obj_tmp->truncated = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile->name, (const xmlChar *)"bndbox") == 0)
{
//szKey = xmlNodeGetContent(curNode_chile);
//cout << "bndbox = " << szKey << endl; //得到node2的值并输出
//xmlFree(szKey);
curNode_chile_child = curNode_chile->xmlChildrenNode;
while (curNode_chile_child->next != NULL)
{
while (xmlStrcmp(curNode_chile_child->name, (const xmlChar *)"text") == 0)
{
curNode_chile_child = curNode_chile_child->next;
}
if (xmlStrcmp(curNode_chile_child->name, (const xmlChar *)"xmin") == 0)
{
szKey = xmlNodeGetContent(curNode_chile_child);
//cout << "xmin = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
obj_tmp->xmin = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile_child->name, (const xmlChar *)"ymin") == 0)
{
szKey = xmlNodeGetContent(curNode_chile_child);
//cout << "ymin = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
obj_tmp->ymin = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile_child->name, (const xmlChar *)"xmax") == 0)
{
szKey = xmlNodeGetContent(curNode_chile_child);
//cout << "xmax = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
obj_tmp->xmax = atoi(stream);
xmlFree(szKey);
}
if (xmlStrcmp(curNode_chile_child->name, (const xmlChar *)"ymax") == 0)
{
szKey = xmlNodeGetContent(curNode_chile_child);
//cout << "ymax = " << szKey << endl; //得到node2的值并输出
//cout << "xmax = " << szKey << endl; //得到node2的值并输出
char * stream = (char*)szKey;
obj_tmp->ymax = atoi(stream);
xmlFree(szKey);
}
curNode_chile_child = curNode_chile_child->next;
}
}
curNode_chile = curNode_chile->next;
}
xml_info->node_nums++;
}
curNode = curNode->next;
}
if (xml_info->node_nums <1)
{
xmlFreeDoc(doc);
return -4;
}
xmlFreeDoc(doc);
return 0;
}
int main(int argc, char *argv[])
{
string xml_path = "D:\\1003959936.xml";
xml_data* xml_info = (xml_data*)malloc(sizeof(xml_data));
memset(xml_info, 0, sizeof(xml_data));
parse_xml_struct_Data(xml_path, xml_info);
free(xml_info )
}
结果为:
-------------------------------------------分割线---------------------------------------------------
将yolo检测到的目标,保存到xml文件中。核心函数记录:
//imgFullName 图片的名字,不带后缀
int write_xml_1(int imgW, int imgH, int channels, detection *dets, int num, float thresh, char *imgFullName, char* saveFolder) //filename:: xml文件名 node::写入的节点名 data:写入的节点数据
{
int selected_detections_num;
int i;
char xminStr[10]; char yminStr[10];
char xmaxStr[10]; char ymaxStr[10];
char imgWidth[10]; char imgHeight[10];
char imgChannel[10];
char filename[500];
int preNameLen = strlen(imgFullName);
memset(filename, 0, 500);
memcpy(filename, imgFullName, preNameLen - 4);
sprintf(filename, "%s.xml", filename);
//selected_detections 从*dets中得到置信度大于thresh(0.25)的元素,并且计算得到了最佳类别和最佳置信度
detection_with_class* selected_detections = get_actual_detections(dets, num, thresh, &selected_detections_num);
xmlDocPtr doc;
doc = xmlReadFile(filename, "UTF-8", XML_PARSE_NOBLANKS);
if (doc == NULL) //文件不存在 创建一个新文件
{
char* imagenameTmp = NULL;
imagenameTmp = G2U(imgFullName);
xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");
xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST"annotation");
xmlNodePtr filename_node = xmlNewTextChild(root_node, NULL, BAD_CAST "filename", BAD_CAST imagenameTmp);
free(imagenameTmp);
//xmlNewTextChild(root_node, NULL, BAD_CAST "size", BAD_CAST data);
//设置根节点
xmlDocSetRootElement(doc, root_node);
xmlNodePtr size_node = xmlNewNode(NULL, BAD_CAST"size");
xmlAddSibling(filename_node, size_node);
xmlNewTextChild(size_node, NULL, BAD_CAST "width", BAD_CAST _itoa(imgW, imgWidth, 10));
xmlNewTextChild(size_node, NULL, BAD_CAST "height", BAD_CAST _itoa(imgH, imgHeight, 10));
xmlNewTextChild(size_node, NULL, BAD_CAST "depth", BAD_CAST _itoa(channels, imgChannel, 10));
bool saveXMLflag = false;
for (i = 0; i < selected_detections_num; ++i)
{
int name = selected_detections[i].best_class;
if (name!=0)
{
continue;
}
saveXMLflag = true;
box b = selected_detections[i].det.bbox;
//printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);
int left = (b.x - b.w / 2.)*imgW;
int right = (b.x + b.w / 2.)*imgW;
int top = (b.y - b.h / 2.)*imgH;
int bot = (b.y + b.h / 2.)*imgH;
if (left < 0) left = 0;
if (right > imgW - 1) right = imgW - 1;
if (top < 0) top = 0;
if (bot > imgH - 1) bot = imgH - 1;
xmlNodePtr object_node = xmlNewNode(NULL, BAD_CAST"object");
xmlAddSibling(filename_node, object_node);
xmlNodePtr name_node = xmlNewTextChild(object_node, NULL, BAD_CAST "name", BAD_CAST "1");
//bndbox
xmlNodePtr bndbox_node = xmlNewNode(NULL, BAD_CAST"bndbox");
xmlAddSibling(name_node, bndbox_node);
xmlNewTextChild(bndbox_node, NULL, BAD_CAST "xmin", BAD_CAST _itoa(left, xminStr, 10));
xmlNewTextChild(bndbox_node, NULL, BAD_CAST "ymin", BAD_CAST _itoa(top, yminStr, 10));
xmlNewTextChild(bndbox_node, NULL, BAD_CAST "xmax", BAD_CAST _itoa(right, xmaxStr, 10));
xmlNewTextChild(bndbox_node, NULL, BAD_CAST "ymax", BAD_CAST _itoa(bot, ymaxStr, 10));
}
if (!saveXMLflag)
{
xmlFreeDoc(doc);
return 0;
}
sprintf(saveFolder, "%s%s", saveFolder, filename);
xmlSaveFormatFileEnc(saveFolder, doc, "UTF-8", 1);
xmlFreeDoc(doc);
return 0;
}
xmlNodePtr cur;
cur = xmlDocGetRootElement(doc);
if (cur == NULL)
{
xmlFreeDoc(doc);
return -1;
}
xmlFreeDoc(doc);
return 0;
}