利用libxml2生成,解析,修改xml文件。
1. 生成xml文件
// createXmlFile.cpp
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <iostream>
using namespace std;
int main()
{
//定義文檔和節點指針
xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");
xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"root");
//設置根節點
xmlDocSetRootElement(doc,root_node);
//在根節點中直接創建節點
xmlNewTextChild(root_node, NULL, BAD_CAST "newNode1", BAD_CAST "newNode1 content");
xmlNewTextChild(root_node, NULL, BAD_CAST "newNode2", BAD_CAST "newNode2 content");
xmlNewTextChild(root_node, NULL, BAD_CAST "newNode3", BAD_CAST "newNode3 content");
//創建一個節點,設置其內容和屬性,然後加入根結點
xmlNodePtr node = xmlNewNode(NULL,BAD_CAST"node2");
xmlNodePtr content = xmlNewText(BAD_CAST"NODE CONTENT"); //注意不是xmlNewTextChild()
xmlAddChild(root_node,node);
xmlAddChild(node,content);
xmlNewProp(node,BAD_CAST"attribute",BAD_CAST "yes");
//創建一個兒子和孫子節點
node = xmlNewNode(NULL, BAD_CAST "son");
xmlAddChild(root_node,node);
xmlNodePtr grandson = xmlNewNode(NULL, BAD_CAST "grandson");
xmlAddChild(node,grandson);
xmlAddChild(grandson, xmlNewText(BAD_CAST "This is a grandson node"));
//存儲xml文檔
int nRel = xmlSaveFile("CreatedXml.xml",doc);
if (nRel != -1)
{
cout<<"一個xml文檔被創建,寫入"<<nRel<<"個字節"<<endl;
}
//釋放文檔內節點動態申請的內存
xmlFreeDoc(doc);
return 0;
}
2. 解析xml文件// parserXmlFile.cpp
#include <libxml/parser.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
xmlDocPtr doc; //定義解析文檔指針
xmlNodePtr curNode; //定義結點指針(你需要它爲了在各個結點間移動)
xmlChar *szKey; //臨時字符串變量
char *szDocName;
if (argc <= 1)
{
printf("Usage: %s docname\n", argv[0]);
return(0);
}
szDocName = argv[1];
doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER); //解析文件
//檢查解析文檔是否成功,如果不成功,libxml將指一個註冊的錯誤並停止。
//一個常見錯誤是不適當的編碼。XML標準文檔除了用UTF-8或UTF-16外還可用其它編碼保存。
//如果文檔是這樣,libxml將自動地爲你轉換到UTF-8。更多關於XML編碼信息包含在XML標準中.
if (NULL == doc)
{
fprintf(stderr,"Document not parsed successfully. \n");
return -1;
}
curNode = xmlDocGetRootElement(doc); //確定文檔根元素
if (NULL == curNode)
{
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return -1;
}
if (xmlStrcmp(curNode->name, BAD_CAST "root"))
{
fprintf(stderr,"document of the wrong type, root node != root");
xmlFreeDoc(doc);
return -1;
}
curNode = curNode->xmlChildrenNode; //子節點集是鏈表
xmlNodePtr propNodePtr = curNode;
while(curNode != NULL)
{
//取出節點中的內容
if (!xmlStrcmp(curNode->name, (const xmlChar *)"newNode"))
{
szKey = xmlNodeGetContent(curNode);
printf("newNode1: %s\n", szKey);
xmlFree(szKey);
}
//查找帶有屬性attribute的節點
if (xmlHasProp(curNode,BAD_CAST "attribute"))
{
propNodePtr = curNode;
}
curNode = curNode->next;
}
//查找屬性
xmlAttrPtr attrPtr = propNodePtr->properties; //屬性集是鏈表
while (attrPtr != NULL)
{
if (!xmlStrcmp(attrPtr->name, BAD_CAST "attribute"))
{
xmlChar* szAttr = xmlGetProp(propNodePtr,BAD_CAST "attribute");
//szAttr要調用函數xmlFree(szAttr)手動刪除否則會發生內存泄露。
cout<<"get attribute = "<<szAttr<<endl;
xmlFree(szAttr);
}
attrPtr = attrPtr->next;
}
xmlFreeDoc(doc);
return 0;
}
3. 修改xml文件// changXmlFile.cpp
#include <libxml/parser.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
xmlDocPtr doc; //定義解析文檔指針
xmlNodePtr curNode; //定義結點指針(你需要它爲了在各個結點間移動)
char *szDocName;
if (argc <= 1)
{
printf("Usage: %s docname\n", argv[0]);
return(0);
}
szDocName = argv[1];
doc = xmlReadFile(szDocName,"GB2312",XML_PARSE_RECOVER); //解析文件
if (NULL == doc)
{
fprintf(stderr,"Document not parsed successfully. \n");
return -1;
}
curNode = xmlDocGetRootElement(doc);
if (NULL == curNode)
{
fprintf(stderr,"empty document\n");
xmlFreeDoc(doc);
return -1;
}
curNode = curNode->children;
while (NULL != curNode)
{
//刪除newNode1
if (!xmlStrcmp(curNode->name, BAD_CAST "newNode1"))
{
xmlNodePtr tempNode;
tempNode = curNode->next; //使用一個臨時變量來存儲斷鏈節點的後續節點
xmlUnlinkNode(curNode); //將當前節點從文檔中斷鏈(unlink),這樣本文檔就不會再包含這個子節點
xmlFreeNode(curNode); //手動刪除斷鏈節點的內存
curNode = tempNode;
continue;
}
//修改node2的屬性值
if (!xmlStrcmp(curNode->name, BAD_CAST "node2"))
{
xmlSetProp(curNode,BAD_CAST "attribute", BAD_CAST "no");
}
//修改newNode2的內容
if (!xmlStrcmp(curNode->name, BAD_CAST "newNode2"))
{
xmlNodeSetContent(curNode, BAD_CAST "content changed");
}
//增加一個屬性
if (!xmlStrcmp(curNode->name, BAD_CAST "newNode3"))
{
xmlNewProp(curNode, BAD_CAST "newAttr", BAD_CAST "YES");
}
//增加一個子節點
if (!xmlStrcmp(curNode->name, BAD_CAST "son"))
{
xmlNewTextChild(curNode, NULL, BAD_CAST "newGrandSon", BAD_CAST "new content");
}
curNode = curNode->next;
}
//存儲xml文檔
int nRel = xmlSaveFile("ChangedXml.xml",doc);
if (nRel != -1)
{
cout<<"一個xml文檔被創建,寫入"<<nRel<<"個字節"<<endl;
}
xmlFreeDoc(doc);
return 0;
}
4. 編譯g++ 源文件 -o 輸出文件 -I"libxml2的頭文件安裝路徑" -lxml2
示例:
libxml2的頭文件與庫放到了/usr/local目錄下
gcc parserXmlFile.cpp -o parserXmlFile -I/usr/local/include/libxml2/ -L/usr/local/lib/libxml2 -lxml2