一、xml文件简介
libxml2 是一个xml的C语言版的解析器,本来是为Gnome项目开发的工具,是一个基于MIT License的免费开源软件。它除了支持C语言外,还支持C++,PHP,Pascal,Ruby,Tcl等,能在windows,linux,solaris,maxosx等平台运行。功能强大。能够满足一般用户的需求。
在一台嵌入式系统中开机上电一般可以选择加载默认配置或者上一次断电之前的配置供选择的选项。还有就是可以实时保存当前系统的状态信息,这一功能就是通过读写xml来实现的。当开机选择为默认设置时,系统就会去读取保存默认信息的xml文件然后去配置系统。读取上一次断电的配置信息也是一样的。保存上次断电的xml文件是系统每隔一段时间实时写入的(具体间隔多少时间看设置了),除此之外还可以保存想要的状态至xml文件中以供系统加载使用。以上是xml在实际项目中使用的一种情况。
二、libxml2的编译与安装
首先在网上下载libxml2,官方下载网址是http://xmlsoft.org/downloads.html,下载完成后执行以下步骤:
1、解压:tar zxvf libxml2-2.7.8.tar.gz
2、进入解压后的安装目录:cd libxml2-2.7.8
3、再执行:./configure –host=arm-xilinx-linux-gnueabi
其中–host=arm-xilinx-linux-gnueabi视使用的交叉编译器而定。在此使用的是xilinx提供的编译器。
4、执行上述步骤后会生成makefile文件。执行make操作后会在当前目录的.lib下有.so的动态库生成(libxml2.so libxml2.so.2 libxml2.so.2.7.8 )。
5、将动态库拷贝到下位机的/usr/lib下。
至此,编写的程序中就可以使用libxml2了。
注意:在编译使用libxml2的程序时,需要注意一下两点
1)、应该在makefile中加入-lxml2对这三个动态库的链接,否则程序是编译不过的。
2)、编译器的链接库中要加入这三个动态库文件,工作项目中的链接库路径是/ti-sdk-am335x/linux-devkit/arm-arago-linux-gnueabi/usr/lib。否则在makefile中虽然指定了链接动态库,但是在路径中没有程序也是编译不过的。
代码中使用到的libxml2中的头文件应该加入到工程中,只需将libxml2-2.7.8\include\libxml中的头文件全部加入到工程文件中即可。
三、libxml2解析
打开system_info.xml文件,其内容如下:
<usr_system_info_root>
<device>
<system_information>
<start_up_times>
<chip>2326chip>
start_up_times>
system_information>
device>
<Device>
<DHCP>OFFDHCP>
<Ip>10.11.13.215Ip>
<Subnet>255.255.255.0Subnet>
<Gateway>192.168.0.1Gateway>
<Power_On>DefaultPower_On>
<Sys_language>EnglishSys_language>
<Sys_gpib>18Sys_gpib>
<Touch_Adjust>
<xMin>4120xMin>
<xMax>154xMax>
<yMin>144yMin>
<yMax>3680yMax>
Touch_Adjust>
Device>
usr_system_info_root>
第一行是xml的版本,以及编码格式。接下来是文件的节点,根节点的开始为( < usr_system_info_root>),结束为( < /usr_system_info_root>)。每一个子节点都是类似的格式定义的。规律是如此的明显。其关系类似于数据结构中的树,之所以这样组织,是因为在解析的时候需要如此,可以一层一层的往下遍历直到找到想要的元素的值。
1)libxml2中常见的数据类型。
xmlDocPtr: xml的文档指针,其在源代码中的定义如下:
typedef struct _xmlDoc xmlDoc;
typedef xmlDoc *xmlDocPtr;
struct _xmlDoc {
void *_private; /* application data */
xmlElementType type; /* XML_DOCUMENT_NODE, must be second ! */
char *name; /* name/filename/URI of the document */
struct _xmlNode *children; /* the document tree */
struct _xmlNode *last; /* last child link */
struct _xmlNode *parent; /* child->parent link */
struct _xmlNode *next; /* next sibling link */
struct _xmlNode *prev; /* previous sibling link */
struct _xmlDoc *doc; /* autoreference to itself */
/* End of common part */
int compression;/* level of zlib compression */
int standalone; /* standalone document (no external refs)
1 if standalone="yes"
0 if standalone="no"
-1 if there is no XML declaration
-2 if there is an XML declaration, but no
standalone attribute was specified */
struct _xmlDtd *intSubset; /* the document internal subset */
struct _xmlDtd *extSubset; /* the document external subset */
struct _xmlNs *oldNs; /* Global namespace, the old way */
const xmlChar *version;/* the XML version string */
const xmlChar *encoding;/* external initial encoding, if any */
void *ids; /* Hash table for ID attributes if any */
void *refs; /* Hash table for IDREFs attributes if any */
const xmlChar *URL; /* The URI for that document */
int charset; /* encoding of the in-memory content
actually an xmlCharEncoding */
struct _xmlDict *dict; /* dict used to allocate names or NULL */
void *psvi; /* for type/PSVI informations */
int parseFlags;/* set of xmlParserOption used to parse the document */
int properties; /* set of xmlDocProperties for this document set at the end of parsing */
};
xmlNodePtr :结点指针,其在源代码中的定义如下:
typedef struct _xmlNode xmlNode;
typedef xmlNode *xmlNodePtr;
struct _xmlNode {
void *_private; /* application data */
xmlElementType type;/* type number, must be second ! */
const xmlChar *name; /* the name of the node, or the entity */
struct _xmlNode *children; /* parent->childs link */
struct _xmlNode *last; /* last child link */
struct _xmlNode *parent; /* child->parent link */
struct _xmlNode *next; /* next sibling link */
struct _xmlNode *prev; /* previous sibling link */
struct _xmlDoc *doc; /* the containing document */
/* End of common part */
xmlNs *ns; /* pointer to the associated namespace */
xmlChar *content; /* the content */
struct _xmlAttr *properties;/* properties list */
xmlNs *nsDef; /* namespace definitions on this node */
void *psvi; /* for type/PSVI informations */
unsigned short line; /* line number */
unsigned short extra; /* extra data for XPath/XSLT */
};
xmlChar :xml中的字符类型,定义为:
typedef unsigned char xmlChar;
2)libxml2中常见的函数函数。
xmlDocPtr xmlParseFile (const char *filename);
解析xml文件,filename为传入的文件名,返回值为xml文档指针,返回为NULL表示出错。
xmlNodePtr xmlDocGetRootElement (xmlDocPtr doc);
获取文档的根节点函数,doc为文档指针,xmlNodePtr 为返回的根节点,返回为NULL表示出错。
xmlNodePtr xmlDocSetRootElement (xmlDocPtr doc, xmlNodePtr root);
设置文档根节点,doc为文档指针,root为根节点。
xmlDocPtr xmlNewDoc (const xmlChar *version);
新建文档的函数,version为版本,一般为”1.0”,xmlDocPtr 为文档指针。
xmlNodePtr xmlNewNode (xmlNsPtr ns, const xmlChar *name);
ns为节点命名空间的结构及其指针,一般为NULL即可,name是节点名,xmlNodePtr 为创建的节点。
xmlNodePtr xmlNewChild (xmlNodePtr parent, xmlNsPtr ns, const xmlChar * name, const xmlChar * content)
创建新的子节点 ,parent为父节点,ns为节点命名空间的结构及其指针,一般为NULL即可,name为节点名,content为节点内容。成功返回创建好的子节点。
int xmlSaveFormatFileEnc (const char *filename,
xmlDocPtr cur,
const char *encoding,
int format);
保存xml文件到文件系统中,filename为路径,cur为文件指针,encoding为编码格式,一般为”UTF-8”,format是否格式化。0表示不格式化,1表示需要格式化。注意:只有当xmlIndentTreeOutput设置为1,或者xmlKeepBlanksDefault(0)时,format设置为1才能生效。
void xmlNodeSetContent (xmlNodePtr cur, const xmlChar *content);
设置一个子节点的内容,cur为需要设置的子节点,content为内容。
xmlChar* xmlNodeGetContent (xmlNodePtr cur);
获取子节点的内容,cur为所获取的子节点,返回值为内容。
void xmlFreeNode (xmlNodePtr cur);
释放节点。
更多函数可以参考libxml2文档。
四、使用示例
保存触摸屏校正值到xml文件:
int dev_save_touch_cali_to_xml_file(touch_adjust_xy_msg* touch_adjust)
{
xmlNodePtr root_node, cur, temp, xmin, xmax, ymin, ymax;
// 获取xml文件的根节点
root_node = dev_xml_get_root_node((char*)"system_info.xml");
if(root_node == NULL)
{
return 0;
}
//获取根节点下的下一个名为"Device"的节点
dev_xml_get_child_node(root_node, &temp, (char*)"Device");
if(temp == NULL)
{
//节点不存在就创建
dev_xml_create_child_node(root_node, &temp,(char*)“usr/config/system_info.xml”,(char*)"Device");
}
dev_xml_get_child_node(temp, &cur, "Touch_Adjust");
if(cur == NULL)
{
dev_xml_create_child_node(temp, &cur, (char*)“usr/config/system_info.xml”, (char*)"Touch_Adjust");
}
dev_xml_get_child_node(cur, &xmin, (char*)"xMin");
if(xmin == NULL)
{
dev_xml_create_child_node(cur, &xmin, (char*)“usr/config/system_info.xml”, (char*)"xMin");
}
dev_xml_get_child_node(cur, &xmax, (char*)"xMax");
if(xmax == NULL)
{
dev_xml_create_child_node(cur, &xmax, (char*)“usr/config/system_info.xml”, (char*)"xMax");
}
dev_xml_get_child_node(cur, &ymin, (char*)"yMin");
if(ymin == NULL)
{
dev_xml_create_child_node(cur, &ymin, (char*)“usr/config/system_info.xml”, (char*)"yMin");
}
dev_xml_get_child_node(cur, &ymax, (char*)"yMax");
if(ymax == NULL)
{
dev_xml_create_child_node(cur, &ymax, (char*)“usr/config/system_info.xml”, (char*)"yMax");
}
char *strxmin = (char*) new char[10];
char *strxmax = (char*) new char[10];
char *strymin = (char*) new char[10];
char *strymax = (char*) new char[10];
sprintf(strxmin, "%d", touch_adjust->xMin);
sprintf(strxmax, "%d", touch_adjust->xMax);
sprintf(strymin, "%d", touch_adjust->yMin);
sprintf(strymax, "%d", touch_adjust->yMax);
dev_xml_set_node_content((char*)“usr/config/system_info.xml”, xmin, (char*)strxmin);
dev_xml_set_node_content((char*)“usr/config/system_info.xml”, xmax, (char*)strxmax);
dev_xml_set_node_content((char*)“usr/config/system_info.xml”, ymin, (char*)strymin);
dev_xml_set_node_content((char*)“usr/config/system_info.xml”, ymax, (char*)strymax);
delete [] strxmin;
delete [] strxmax;
delete [] strymin;
delete [] strymax;
system("sync");
return 1;
}
从xml文件中读取触摸校正值:
int dev_read_touch_cali_from_xml_file(touch_adjust_xy_msg* touch_adjust)
{
xmlNodePtr root_node, cur, temp, xmin, xmax, ymin, ymax;
root_node = dev_xml_get_root_node((char*)“usr/config/system_info.xml”);
if(root_node == NULL)
{
return 0;
}
dev_xml_get_child_node(root_node, &temp, (char*)"Device");
if(temp == NULL)
{
return 0;
}
dev_xml_get_child_node(temp, &cur,(char*)"Touch_Adjust");
if(cur == NULL)
{
return 0;
}
dev_xml_get_child_node(cur, &xmin, (schar *)"xMin");
if(xmin == NULL)
{
return 0;
}
dev_xml_get_child_node(cur, &xmax, (char*)"xMax");
if(xmax == NULL)
{
return 0;
}
dev_xml_get_child_node(cur, &ymin, (char*)"yMin");
if(ymin == NULL)
{
return 0;
}
dev_xml_get_child_node(cur, &ymax, (char*)"yMax");
if(ymax == NULL)
{
return 0;
}
char *strxmin;
char *strxmax;
char *strymin;
char *strymax;
dev_xml_get_node_content(xmin, &strxmin);
dev_xml_get_node_content(xmax, &strxmax);
dev_xml_get_node_content(ymin, &strymin);
dev_xml_get_node_content(ymax, &strymax);
sscanf(strxmin, "%d", &touch_adjust->xMin);
sscanf(strxmax, "%d", &touch_adjust->xMax);
sscanf(strymin, "%d", &touch_adjust->yMin);
sscanf(strymax, "%d", &touch_adjust->yMax);
xmlFree(strxmin);
xmlFree(strxmax);
xmlFree(strymin);
xmlFree(strymax);
return 1;
}