Linux下xml学习

来源:互联网 发布:windows phone 8.1降级 编辑:程序博客网 时间:2024/05/22 03:14

     Linuxxml学习

一、下载xml软件包:tinyxml_2_6_2.zip

Tinyxml(轻量级c++)下载地址:http://sourceforge.net/projects/tinyxml/?source=dlp

Tinyxml压缩包里面其实有用的只有几个文件:

tinystr.cpp  tinystr.h  tinyxml.cpp  tinyxmlerror.cpp  tinyxml.h  tinyxmlparser.cpp

makefile

四个cpp文件和两个h头文件,以及一个makefile文件。

二、解压

#unzip tinyxml_2_6_2.zip

解压好后,进入解压目录

# cd tinyxml

编译

#make

最后将生成如下信息:


即产生tinyxml自带的测试程序,xmltest 可执行文件。在tinyxml目录下可以看见编译成功的可执行文件xmltest,运行xmltest将会输出测试信息。

三、生成tinyxml动态库,修改makefile内容(仅列出修改部分)

#**************************************************************************

# Targets of the build

#**************************************************************************

OUTPUT := xmltest 

LIB := libtinyxml.so  #增加生成libtinyxml.so目标

all: ${OUTPUT} ${LIB}

#**************************************************************************

# Source files

#**************************************************************************

SRCS := tinyxml.cpp tinyxmlparser.cpp xmltest.cpp tinyxmlerror.cpp tinystr.cpp

# Add on the sources for libraries

SRCS := ${SRCS}

OBJS := $(addsuffix .o,$(basename ${SRCS}))

LIBOBJS := tinyxml.o tinyxmlparser.o tinyxmlerror.o tinystr.o

#**************************************************************************

# Output

#**************************************************************************

${OUTPUT}: ${OBJS}

${LD} -o $@ ${LDFLAGS} ${OBJS} ${LIBS} ${EXTRA_LIBS}

${LIB}: ${LIBOBJS}

ar -r $@ ${LIBOBJS}

#**************************************************************************

# common rules

#**************************************************************************

# Rules for compiling source files to object files

%.o : %.cpp

${CXX} -c ${CXXFLAGS} ${INCS} $< -o $@

%.o : %.c

${CC} -c ${CFLAGS} ${INCS} $< -o $@

dist:

bash makedistlinux

clean:

-rm -f core ${OBJS} ${OUTPUT} ${LIB} ${TEST}

其中红色与蓝色部分为添加部分,再一次执行make的时候,将在tinyxml目录下产生一个动态库文件libtinyxml.so

四、linuxc程序对xml库的调用处理

由于cc++函数在编译后,产生的函数符号会不同,所以,要想c能正确地调用c++动态库中的函数,必须要把c++库函数封装成c函数的接口。采取的方式就是,c++函数名前面添加extern “C”,编译生成动态库后,在c程序中,只要用externc++中的函数名申明一次,就可以在c程序中直接使用了。

1、把libtinyxml.so封装成c接口的动态库形式,新建myxml.cpp,用来生成c接口动态库。各接口内容如下:

#include "tinyxml.h"  

#include "tinystr.h"  

  

//xml文件申明结构体 

typedef struct XmlDeclaration

{

char version[8];     //版本号

char encoding[8];  //编码

char standalone[4];  //独立性,yes或者no

}; 

  

/*******************************************************************

** 函数: AddXmlElement

** 功能: 向父节点添加子节点元素

** 参数: pParentNode  -- 父节点指针

**        pcKey   -- 元素名

**        pcValue -- pcKey对应的值

** 返回值: 添加成功返回 0,否则返回 -1

**/

int AddXmlElement(TiXmlElement *pParentNode, const char *pcKey, const char *pcValue)

{

int nRet = -1;

if(pParentNode == NULL || pcKey == NULL || pcValue == NULL)

{

return nRet;

}

TiXmlElement *pChildElement = new TiXmlElement(pcKey);

if(pChildElement == NULL)

{

return nRet;

}

    pParentNode->LinkEndChild(pChildElement);

    

TiXmlText *pChildContent = new TiXmlText(pcValue);

    if(pChildContent == NULL)

{

return nRet;

}

pChildElement->LinkEndChild(pChildContent);

nRet = 0;

return nRet;

}

/*******************************************************************

** 函数: GetNodePointerByKey

** 功能: 获取xml文件中某个类型节点的指针,递归调用

** 参数: pRootNode  -- xml文件根节点指针

**        pcKey      -- 查询的元素名(即类型)

**        pNode      -- pcKey对应的节点,输出参数

** 返回值: 获取成功返回 0,否则返回 -1

**/

int GetNodePointerByKey(TiXmlElement* pRootNode, const char *pcKey, TiXmlElement *&pNode)  

{  

const char * pType = pRootNode->Value();

    // 假如等于根节点名,就退出  

    if (strncmp(pType, pcKey, strlen(pcKey)) == 0)  

    { 

        pNode = pRootNode;  

        

return 0;  

    }

TiXmlElement* pEle = pRootNode;    

    for (pEle = pRootNode->FirstChildElement(); pEle; pEle = pEle->NextSiblingElement())    

    {    

        //递归处理子节点,获取节点指针  

        if(GetNodePointerByKey(pEle, pcKey, pNode) == 0)  

        {

return 0;

}

    }    

    

return -1;  

/*******************************************************************

** 函数: GetXmlElementText

** 功能: 获取xml文件中元素对应的值

** 参数: pcPath  -- xml文件路径

**        pcKey   -- 查询的元素名(即类型)

**        pcValue -- pcKey对应的值,输出参数,需要事先分配空间并初始化

** 返回值: 获取成功返回 0,否则返回 -1

**/

extern "C" int GetXmlElementText(const char *pcPath, char *pcKey, char *pcValue)

{

int nRet = -1;

TiXmlElement *pNode = NULL;

//定义一个TiXmlDocument类指针  

    TiXmlDocument *pDoc = new TiXmlDocument();  

    if (pDoc == NULL)  

    {  

        return nRet;  

    } 

    pDoc->LoadFile(pcPath);  

//获取根节点

TiXmlElement *rootElement = pDoc->RootElement();

nRet = GetNodePointerByKey(rootElement, pcKey, pNode);

if(nRet == 0)

{

//获取该元素pcKey对应的值

const char * pText = pNode->GetText();

if(pText != NULL)

{

strncpy(pcValue, pText, strlen(pText));

}

else

{

nRet = -1;

}

}

return nRet;

}

/*******************************************************************

** 函数: DeleteXmlElement

** 功能: 删除xml文件中的元素

** 参数: pcPath  -- xml文件路径(包括文件名)

**        pcKey   -- 删除的元素名(即类型)

** 返回值: 删除成功返回 0,否则返回 -1

**/

extern "C" int DeleteXmlElement(const char *pcPath,  char *pcKey)

{    

int nRet = -1;

TiXmlElement *pNode = NULL;  

if(pcPath == NULL || pcKey == NULL)

{

return nRet;

}

//定义一个TiXmlDocument类指针  

    TiXmlDocument *pDoc = new TiXmlDocument();  

    if (pDoc == NULL)  

    {  

        return nRet;  

    } 

    pDoc->LoadFile(pcPath);  

    TiXmlElement *pRootEle = pDoc->RootElement();  

    if (pRootEle == NULL)  

    {  

        return nRet;  

    }  

    //查询节点

    nRet = GetNodePointerByKey(pRootEle, pcKey, pNode);

if(nRet == 0)

{

// 假如是根节点  

if (pRootEle == pNode)  

{  

if(pDoc->RemoveChild(pRootEle))  

{  

   pDoc->SaveFile(pcPath);  

   

   nRet = 0;

else

{

nRet = -1;

}

return nRet;

// 假如是其它节点  

if (pNode != NULL)  

{  

TiXmlNode *pParNode =  pNode->Parent();  

if (pParNode != NULL)  

{

TiXmlElement* pParentEle = pParNode->ToElement();  

if (pParentEle != NULL)  

{  

if(pParentEle->RemoveChild(pNode))

{

pDoc->SaveFile(pcPath);

nRet = 0;

}

else

{

nRet = -1;

}

}

else

{

nRet = -1;

}

}

else

{

nRet = -1;

}

}  

else 

{  

nRet = -1; 

}  

}

else

{

nRet = -1;

}

return nRet;

}

/*******************************************************************

** 函数: ModifyNodeTextByKey

** 功能: 通过节点类型修改节点文本

** 参数: pcPath  -- xml文件路径(包括文件名)

**        pcKey   -- 元素名

**        pcValue -- pcKey对应的值

** 返回值: 修改成功返回 0,否则返回 -1

**/

extern "C" int ModifyNodeTextByKey(const char *pcPath, const char *pcKey,

const char *pcValue)

{

int nRet = -1;

    // 定义一个TiXmlDocument类指针

    TiXmlDocument *pDoc = new TiXmlDocument();

    if (pDoc == NULL)

    {

        return nRet;

    }

    pDoc->LoadFile(pcPath);

    TiXmlElement *pRootEle = pDoc->RootElement();

    if (pRootEle == NULL)

    {

        return nRet;

    }

    TiXmlElement *pNode = NULL;

    GetNodePointerByKey(pRootEle, pcKey, pNode);

    if (pNode != NULL)

    {

// 首先清除所有文本

        pNode->Clear();  

        // 然后插入文本,保存文件

        TiXmlText *pValue = new TiXmlText(pcValue);

        pNode->LinkEndChild(pValue);

        pDoc->SaveFile(pcPath);

nRet = 0;

    }

    else

{

nRet = -1;

    }

return nRet;

}

/*******************************************************************

** 函数名: CreatXmlFile

** 功能:   创建xml文件

** 参数:   pcPath     -- 创建的xml文件路径(包括文件名)

**          pcRootElem -- xml文件第一个根节点的名字

**          pstrDecla  -- xml文件的申明数据结构体

** 返回值: 成功返回0,否则返回-1

 */

extern "C" int CreatXmlFile(const char *pcPath, const char *pcRootElem,

 struct XmlDeclaration *pstrDecla)

{

int nRet = -1;

if(pcPath == NULL || pcRootElem == NULL)

{

return nRet;

}

//创建一个XML的文档对象

    TiXmlDocument *configXml = new TiXmlDocument();

if(configXml == NULL)

{

return nRet;

}

//申明

if(pstrDecla != NULL)

{

TiXmlDeclaration  Declaration(pstrDecla->version,  pstrDecla->encoding,

                  pstrDecla->standalone);

configXml->InsertEndChild(Declaration);

}

//产生根节点(pcRootElem)

    TiXmlElement *rootElement = new TiXmlElement(pcRootElem);

if(rootElement == NULL)

{

return nRet;

}

    configXml->LinkEndChild(rootElement);

nRet = 0;

//打印生成的xml文件内容

//configXml->Print();

    

//写文件

configXml->SaveFile(pcPath);

return nRet;

}

/*******************************************************************

** 函数名: InsertNodeElem

** 功能:   向某个父节点插入子节点元素

** 参数:   pcPath      -- 创建的xml文件路径(包括文件名)

**          pcParentKey -- 父节点名字

**          pcKey       -- 子节点元素的名字

**          pcValue     -- pcKey对应的值,如果为空值,将产生一个pcKey的空节点

** 返回值: 成功返回0,否则返回-1

 */

extern "C" int InsertNodeElem(const char *pcPath, const char *pcParentKey, const char *pcKey, 

const char *pcValue)

{

int nRet = -1;

if(pcPath ==NULL || pcParentKey == NULL || pcKey == NULL)

{

return nRet;

}

    // 定义一个TiXmlDocument类指针

    TiXmlDocument *pDoc = new TiXmlDocument();

    if (pDoc == NULL)

    {

        return nRet;

    }

    pDoc->LoadFile(pcPath);

    TiXmlElement *pRootEle = pDoc->RootElement();

    if (pRootEle == NULL)

    {

        return nRet;

    }

    TiXmlElement *pNode = NULL;

//找到父节点指针

    GetNodePointerByKey(pRootEle, pcParentKey, pNode);

if(pNode != NULL)

{

if(pcValue != NULL)

{

//添加子节点元素

AddXmlElement(pNode, pcKey, pcValue);

}

else

{

AddXmlElement(pNode, pcKey, "");

}

pDoc->SaveFile(pcPath);

nRet = 0;

}

return nRet;

/*******************************************************************

** 函数名: PrintXmlFile

** 功能:   显示xml文件内容

** 参数:   pcPath -- 创建的xml文件路径(包括文件名)

** 返回值: 无

 */

extern "C" void PrintXmlFile(const char *pcPath)

{

if(pcPath == NULL)

{

return;

}

    TiXmlDocument *pDoc = new TiXmlDocument();  

    if (pDoc == NULL)  

    {  

        return;  

    }  

    pDoc->LoadFile(pcPath);  

    pDoc->Print();  

return;

}

以上凡是函数名前被extern "C"修饰的函数,都是提供给c直接调用的接口。创建一个文件夹xmlso,把myxml.cpp、libtinyxml.so、tinyxml.h、tinystr.h文件拷贝到该目录,运行如下命令产生c接口的动态库myxml.so。

g++ -fPIC -shared -o myxml.so myxml.cpp ./libtinyxml.so

五、测试动态库myxml.so

创建test.h头文件,内容如下:

#ifndef _MYXML_H

#define _MYXML_H

//xml文件申明结构体 

typedef struct XmlDeclaration

{

char version[8];     //版本号

char encoding[8];  //编码

char standalone[4];  //独立性,yes或者no

}XmlDeclarationData; 

/*******************************************************************

** 函数: GetXmlElementText

** 功能: 获取xml文件中元素对应的值

** 参数: pcPath  -- xml文件路径

**        pcKey   -- 查询的元素名(即类型)

**        pcValue -- pcKey对应的值,输出参数,需要事先分配空间并初始化

** 返回值: 获取成功返回 0,否则返回 -1

**/

extern int GetXmlElementText(const char *pcPath, char *pcKey, char *pcValue);

/*******************************************************************

** 函数: DeleteXmlElement

** 功能: 删除xml文件中的元素

** 参数: pcPath  -- xml文件路径(包括文件名)

**        pcKey   -- 删除的元素名(即类型)

** 返回值: 删除成功返回 0,否则返回 -1

**/

extern int DeleteXmlElement(const char *pcPath,  char *pcKey);

/*******************************************************************

** 函数: ModifyNodeTextByKey

** 功能: 通过节点类型修改节点文本

** 参数: pcPath  -- xml文件路径(包括文件名)

**        pcKey   -- 元素名

**        pcValue -- pcKey对应的值

** 返回值: 修改成功返回 0,否则返回 -1

**/

extern int ModifyNodeTextByKey(const char *pcPath, const char *pcKey,const char *pcValue);

/*******************************************************************

** 函数名: CreatXmlFile

** 功能:   创建xml文件

** 参数:   pcPath     -- 创建的xml文件路径(包括文件名)

**          pcRootElem -- xml文件第一个根节点的名字

**          pstrDecla  -- xml文件的申明数据结构体

** 返回值: 成功返回0,否则返回-1

 */

extern int CreatXmlFile(const char *pcPath, const char *pcRootElem, 

struct XmlDeclaration *pstrDecla);

/*******************************************************************

** 函数名: InsertNodeElem

** 功能:   向某个父节点插入子节点元素

** 参数:   pcPath      -- 创建的xml文件路径(包括文件名)

**          pcParentKey -- 父节点名字

**          pcKey       -- 子节点元素的名字

**          pcValue     -- pcKey对应的值,如果为空值,将产生一个pcKey的空节点

** 返回值: 成功返回0,否则返回-1

 */

extern int InsertNodeElem(const char *pcPath, const char *pcParentKey, const char *pcKey,

 const char *pcValue);

/*******************************************************************

** 函数名: PrintXmlFile

** 功能:   显示xml文件内容

** 参数:   pcPath -- 创建的xml文件路径(包括文件名)

** 返回值: 无

 */

extern void PrintXmlFile(const char *pcPath);

#endif//ifndef _MYXML_H

C程序中只要包含该头文件,就可以直接调用myxml.so动态库中的c接口函数,创建test.c程序,内容如下:

#include <stdio.h>

#include <string.h>

#include "myxml.h"

int main()

{

char *p = "test.xml";

XmlDeclarationData strD;

char cTmp[256] = {0};

int nRet = -1;

//xml申明结构体

memset(&strD, 0, sizeof(strD));

memcpy(strD.version, "1.0", 3);

memcpy(strD.encoding, "utf-8", 5);

memcpy(strD.standalone, "yes", 3);

//创建一个xml文件

CreatXmlFile(p, "Root", &strD);

//增加节点

InsertNodeElem(p, "Root", "No1", "Best boy");

InsertNodeElem(p, "Root", "No2", "");

InsertNodeElem(p, "No2", "No3", "");

InsertNodeElem(p, "No3", "No4", "end");

//打印xml文件

PrintXmlFile(p);

//获取节点元素

nRet = GetXmlElementText(p, "No3", cTmp);

printf("nRet:%d  cTmp: %s \r\n", nRet, cTmp);

//获取节点元素

nRet = GetXmlElementText(p, "No4", cTmp);

printf("nRet:%d  cTmp: %s \r\n", nRet, cTmp);

//修改节点元素

nRet = ModifyNodeTextByKey(p, "No1", "start");

//打印节点元素

PrintXmlFile(p);

//删除节点元素

nRet = DeleteXmlElement(p, "No1");

printf("nRet:%d   \r\n", nRet);

//打印节点元素

PrintXmlFile(p);

return 0;

}

把myxml.so、test.htest.c放在同一目录,编译:

gcc -o test test.c ./myxml.so

将在目录中产生test可执行文件,运行./test,会生成test.xml文件,输出如下信息:


原创粉丝点击