一、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文件,其內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<usr_system_info_root>
<device>
<system_information>
<start_up_times>
<chip>2326</chip>
</start_up_times>
</system_information>
</device>
<Device>
<DHCP>OFF</DHCP>
<Ip>10.11.13.215</Ip>
<Subnet>255.255.255.0</Subnet>
<Gateway>192.168.0.1</Gateway>
<Power_On>Default</Power_On>
<Sys_language>English</Sys_language>
<Sys_gpib>18</Sys_gpib>
<Touch_Adjust>
<xMin>4120</xMin>
<xMax>154</xMax>
<yMin>144</yMin>
<yMax>3680</yMax>
</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;
}