Linux下xml学习
来源:互联网 发布:windows phone 8.1降级 编辑:程序博客网 时间:2024/05/22 03:14
Linux下xml学习
一、下载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。
四、linux下c程序对xml库的调用处理
由于c与c++函数在编译后,产生的函数符号会不同,所以,要想c能正确地调用c++动态库中的函数,必须要把c++库函数封装成c函数的接口。采取的方式就是,c++函数名前面添加extern “C”,编译生成动态库后,在c程序中,只要用extern把c++中的函数名申明一次,就可以在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.h、test.c放在同一目录,编译:
gcc -o test test.c ./myxml.so
将在目录中产生test可执行文件,运行./test,会生成test.xml文件,输出如下信息:
- Linux下xml学习
- linux下 XML 的学习总结
- linux下使用xml
- linux下XML编程
- linux下格式xml
- linux下使用xml
- linux下 libxml2 xml解析
- linux下opencv训练xml
- Ant 下build.xml学习
- 学习下linux
- Linux下TC学习
- linux下学习OpenGL
- linux下学习python
- linux下C++学习
- linux下FrameBuffer学习
- Linux下进程学习
- linux下shell学习
- linux下FrameBuffer学习
- 产品经理和项目经理
- 反向Ajax,第5部分:事件驱动的Web开发
- PHP has encountered an Access Violation at *** 的问题
- 博士遇"原始学历歧视"本科"211"强过博士帽?
- 单步执行---面向对象程序
- Linux下xml学习
- 秒杀多线程第二篇 原子操作 Interlocked系列函数
- 程序猿转行外贸
- .net如何使用 TransactionScope
- 一种C++ DLL接口封装的基本方法
- Linux内核的时钟中断
- Java对存储过程的调用方法
- Android权限列表permission说明 (一)
- 解决混合模式程序集在VS2010 .net 4.0 环境下调试出错的方法。