说明:文章中代码是我参考别人的例子得来的。
XML基础
一、XML的概念
Xml是一种可扩展标记语言。在电子计算机中,标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种的信息比如文章等。xml可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
1、Xml有以下特点:
Xml是一种标记语言,类似HTML
XML的设计宗旨是传输数据,而非显示数据
XML的标签没有被预定义。您需要自行定义标签。
XML被设计为具有自我描述性。
2、可扩展标记语言和超文本标记语言之间的差异
可扩展标记语言被设计用来传输和存储数据,其焦点是数据的内容。
超文本标记语言被设计用来显示数据,其焦点是数据的外观。
二、XML的用途
XML仅仅是纯文本,没有任何行为。可以通俗的理解为一种带格式的文本。
XML由于它的特性常被用来简化数据的存储和共享。举如下例子:
1、XML 把数据从 HTML 分离
如果你需要在 HTML 文档中显示动态数据,那么每当数据改变时将花费大量的时间来编辑 HTML。通过 XML,数据能够存储在独立的 XML 文件中。这样你就可以专注于使用 HTML 进行布局和显示,并确保修改底层数据不再需要对 HTML 进行任何的改变。
2、XML 简化数据共享
在真实的世界中,计算机系统和数据使用不兼容的格式来存储数据。
XML 数据以纯文本格式进行存储,因此提供了一种独立于软件和硬件的数据存储方法。
3、XML 简化数据传输
通过 XML,可以在不兼容的系统之间轻松地交换数据。
对开发人员来说,其中一项最费时的挑战一直是在因特网上的不兼容系统之间交换数据。由于可以通过各种不兼容的应用程序来读取数据,以 XML 交换数据降低了这种复杂性。
4、XML 简化平台的变更
升级到新的系统(硬件或软件平台),总是非常费时的。必须转换大量的数据,不兼容的数据经常会丢失。XML 数据以文本格式存储。这使得 XML 在不损失数据的情况下,更容易扩展或升级到新的操作系统、新应用程序或新的浏览器。
5、XML 使您的数据更有用
由于 XML 独立于硬件、软件以及应用程序,XML 使您的数据更可用,也更有用。
不同的应用程序都能够访问您的数据,不仅仅在 HTML 页中,也可以从 XML 数据源中进行访问。
三、简要的XML使用例子
例子中主要依赖libxml2库来进行对XML文档的操作。
1、创建一简易的XML文档
大致步骤如下:
(1)、建立XML文档和根节点,并将根节点绑定到XML文档
(2)、建立一个节点,设置一些属性,然后将该节点添加到根节点下
(3)、在上个节点下增加一个子节点,往子节点添加内容
(4)、重复(2)、(3)步骤增加一个节点
(5)、保存XML文档,释放相应资源
#include<string.h> #include<stdlib.h> #include<libxml2/libxml/tree.h> #include<libxml2/libxml/parser.h> #include<libxml2/libxml/xmlstring.h> int main(int argc,char **argv)
{
xmlInitParser();
//建立XML文档和根结点
xmlDocPtr doc = xmlNewDoc( "1.0");
xmlNodePtr root = xmlNewNode(NULL, "List");
//将根节点绑定到XM L文档
xmlDocSetRootElement(doc, root);
//建立Person结点,为其安装四个属性
xmlNodePtr nodeTsybius = xmlNewNode(NULL, "Person");
xmlNewProp(nodeTsybius, "Id", "1001");
xmlNewProp(nodeTsybius, "Name", "Tsybius");
xmlNewProp(nodeTsybius, "Sex", "Male");
xmlNewProp(nodeTsybius, "Age", "23");
xmlAddChild(root, nodeTsybius);
//在Person结点下安放子结点,并为子节点添加内容
xmlNewTextChild(nodeTsybius, NULL, "Achievement", "ABC Rank 2");
xmlNewTextChild(nodeTsybius, NULL, "Achievement", "DEF Rank 4");
xmlNodePtr nodeGalatea = xmlNewNode(NULL, "Person");
xmlNewProp(nodeGalatea, "Id", "1002");
xmlNewProp(nodeGalatea, "Name", "Galatea");
xmlNewProp(nodeGalatea, "Sex", "Female");
xmlNewProp(nodeGalatea, "Age", "21");
xmlAddChild(root, nodeGalatea);
xmlNewTextChild(nodeGalatea, NULL, "Achievement", "ABC Rank 1");
xmlNewTextChild(nodeGalatea, NULL, "Achievement", "XYZ Rank 2");
xmlNewTextChild(nodeGalatea, NULL, "Achievement", "MNOP Rank 5");
//保存XML文档
int nRel = xmlSaveFile("src/List.xml", doc);
if(nRel != -1)
{
printf("List.xml: Created Successfully! ");
}
//释放资源
xmlFreeDoc(doc);
xmlCleanupParser();
return EXIT_SUCCESS;
}
2、解析上面创建的XML文档并打印其中内容
大致步骤如下:
(1)、打开XML文件并找到该XML文档的根节点
(2)、找到该根节点下的第一个子节点,找出该节点的属性并打印
(3)、遍历该节点下的带文本内容的子节点,得到文本内容并打印
(4)、转到根节点下的下一个子节点,对该节点的属性进行比较、修改和
修改该节点下的第一个内容子节点的内容
(5)、打印该节点的属性和其子节点的内容,比对是否修改成功
(6)保存XML文档,释放相应资源
#include<string.h> #include<stdlib.h> #include<libxml2/libxml/tree.h> #include<libxml2/libxml/parser.h> #include<libxml2/libxml/xmlstring.h> #define spc(level) PrintSpace(level) //输出缩进用的空格(4个) static void PrintSpace(int level) { int counter; for( counter= 0; counter < level; counter++) { printf(" "); } } //解析XML文档 //static int main(int argc ,char** argv) { xmlInitParser(); //打开xml文件 xmlDocPtr doc = xmlReadFile("src/List.xml","UTF-8", XML_PARSE_NOBLANKS); if(doc == NULL) { printf("Error:can't open List.xml"); exit(1); } //找到首节点 xmlNodePtr root = xmlDocGetRootElement(doc); if(root == NULL) { printf("Error:Can't find the root! "); exit(1); } //建立两个子节点 xmlNodePtr person; xmlNodePtr achivm; spc( 0); printf("Name:%s ",root->name); person=root->children; //逐个找出属性 spc(1);printf("Node:%s ",person->name); spc(2);printf("Id:%s ",xmlGetProp(person,"Id")); spc(2);printf("Name:%s ",xmlGetProp(person,"Name")); spc(2);printf("Sex:%s ",xmlGetProp(person,"Sex")); spc(2);printf("Age:%s ",xmlGetProp(person,"Age")); //打印子节点内容 for(achivm=person->children;achivm;achivm=achivm->next) { spc(3); printf("Node:%s ",achivm->name); printf("Content:%s ",xmlNodeGetContent(achivm)); printf("End "); } spc(1); printf("End "); //一个Person结点遍历结束 //转到下一个Person结点 person = person -> next; //查看某属性是否与某字符串相等 if(xmlStrcmp(xmlGetProp(person, "Name"), (const xmlChar*)"Galatea")) { spc(1); printf(">> The next person is Galatea! "); } else { spc(1); printf(">> The next person is not Galatea! "); } //查看某结点是否有某属性 if(xmlHasProp(person, "Height")) { spc(1); printf(">> The node person has attribute: Height! "); } else { spc(1); printf(">> The next person does not have attribute: Height! "); } //修改属性(Attribute) xmlSetProp(person, (const xmlChar*) "Age", (const xmlChar*) "22");spc(1); printf(">> Change Galatea's age from 21 to 22! "); //修改子结点中的内容(Content) xmlNodeSetContent(person -> children, (const xmlChar*) "NEW Rank 1"); spc(1); printf(">> Change Galatea's 1st achievement to NEW Rank 1 "); spc(1);printf("Node:%s ",person->name); spc(2);printf("Id:%s ",xmlGetProp(person,"Id")); spc(2);printf("Name:%s ",xmlGetProp(person,"Name")); spc(2);printf("Sex:%s ",xmlGetProp(person,"Sex")); spc(2);printf("Age:%s ",xmlGetProp(person,"Age")); //打印子节点内容 for(achivm=person->children;achivm;achivm=achivm->next) { spc(3); printf("Node:%s ",achivm->name); printf("Content:%s ",xmlNodeGetContent(achivm)); printf("End "); } spc(1); printf("End "); spc(0); printf("End "); int nRel = xmlSaveFile("src/List.xml", doc); if(nRel != -1) { printf("List.xml: Created Successfully! "); } xmlFree(achivm); xmlFree(person); xmlFree(root); xmlFree(doc); xmlCleanupParser(); return EXIT_SUCCESS; }
说明:如果时多线程编程,xmlInitParser()与xmlCleanupParser()只能在主线程中调用