RAPIDxml的使用「建议收藏」

RAPIDxml的使用「建议收藏」对RAPIDxml使用的介绍和举例。

大家好,又见面了,我是你们的朋友全栈君。

一直以来,在代码没有任何限制的使用XML编解码情况下,服务器代码性能会非常低下。

要提高服务器性能:

一种方案是优化原有架构,只在对外接口及考虑后期可能扩展的接口使用XML编解码,在内部处理尽量使用二进制(结构体)编码,效率会大大提升。这个原因不用解释也很清楚,效率低下的字符串匹配变为二进制匹配,效率提升哪绝对是可观的!!!

还有一种方案,不改变原有架构(很可能模块很多,代码逻辑复杂,重新将原来的XML转换为二进制,代码修改量大),替换原来的XML解析库,提高XML解析效率。这种绝对没有第一种效率提升高,但如果选好库,提升有时也很大。

XML解析库当然不用自己去写了,借鉴前辈大能们的写的经过战火考验的开源库是最好的办法。

分析现有的开源XML库,大家比较常用的是TINYxml,小巧灵活,效率也不差。最近在查找资料是发现有一种和RAPIDjson对应的RAPIDxml解析库,号称效率是TINYxml的十几倍到几十倍,很多用过的兄弟都在大力推荐。

写了个测试代码试用了一下,发现确实不错,编译很方便,没什么需要特别注意的,编码使用和TINYxml相似,但更简单。不过比TINYxml使用上技术“难度”要大一些–这是因为RAPIDxml为了提高解析速度,不会重新复制XML字符串,都是直接在原字符串上解析并修改,如果对指针、内存理解不深,使用不准确很可能会引起解析或者内存异常,程序崩溃。

下面附简单的使用举例:

//文件包含

#include “..\..\3rd\include\rapidxml\rapidxml.hpp”
#include “..\..\3rd\include\rapidxml\rapidxml_print.hpp”
#include “..\..\3rd\include\rapidxml\rapidxml_iterators.hpp”
#include “..\..\3rd\include\rapidxml\rapidxml_utils.hpp”
using namespace rapidxml;

void test_rapidxml_create()
{

//创建测试
xml_document<wchar_t> doc; //析构时会自动释放内存,allocate_node相关会自动在对象析构时释放整个pool内存
xml_node<wchar_t>* rot = doc.allocate_node(rapidxml::node_pi,doc.allocate_string(L”xml version=’1.0′ encoding=’utf-8′”));  
//xml_node<wchar_t>* rot = doc.allocate_node(rapidxml::node_pi, L”xml version=’1.0′ encoding=’utf-8′”); //不能这样用,内部用到的临时字符串在xml分配时只会复制指针,不会申请内存

doc.append_node(rot);
xml_node<wchar_t>* node = doc.allocate_node(node_element, doc.allocate_string(L”text”), NULL);    
xml_node<wchar_t>* row = doc.allocate_node(node_element, doc.allocate_string(L”row”), doc.allocate_string(L”3″));    
doc.append_node(node);  
node->append_node(row); 

xml_node<wchar_t>* row0 = doc.allocate_node(node_element, doc.allocate_string(L”row_0″), NULL);    
xml_node<wchar_t>* row1 = doc.allocate_node(node_element, doc.allocate_string(L”row_1″), NULL); 
xml_node<wchar_t>* row2 = doc.allocate_node(node_element, doc.allocate_string(L”row_2″), NULL); 
row->append_node(row0);
row->append_node(row1);
row->append_node(row2);

row0->append_node(doc.allocate_node(node_element, doc.allocate_string(L”name”), doc.allocate_string(L”wang”)));  
row0->append_node(doc.allocate_node(node_element, doc.allocate_string(L”tel”), doc.allocate_string(L”133xxxx”)));  
row0->append_node(doc.allocate_node(node_element, doc.allocate_string(L”住址”), doc.allocate_string(L”北 京”))); 

row1->append_node(doc.allocate_node(node_element, doc.allocate_string(L”name”), doc.allocate_string(L”li”)));  
row1->append_node(doc.allocate_node(node_element, doc.allocate_string(L”tel”), doc.allocate_string(L”135xxxx”)));  
row1->append_node(doc.allocate_node(node_element, doc.allocate_string(L”住址”), doc.allocate_string(L”西 安?”))); 

row2->append_node(doc.allocate_node(node_element, doc.allocate_string(L”name”), doc.allocate_string(L”zhang”)));  
row2->append_node(doc.allocate_node(node_element, doc.allocate_string(L”tel”), doc.allocate_string(L”137xxxx”)));  
row2->append_node(doc.allocate_node(node_element, doc.allocate_string(L”住址”), doc.allocate_string(L”太 原2#”))); 

std::wstring sOut;    
rapidxml::print(std::back_inserter(sOut), doc, 0);  
wprintf(L”\n===========================\ntest xml create doc:\n%s\n”, sOut.c_str());
}

void test_rapidxml_error()
{

//#define RAPIDXML_NO_EXCEPTIONS
//异常测试
xml_document<wchar_t> doc;

//doc.parse<0>(L”<text>111</text>”);//临时变量内存释放的异常不是xml解析异常,是windows内存访问异常  
try 
{  
wchar_t  strXml[] = L”<text><row>”;
doc.parse<0>(strXml);//会改变参数的内容,strXml的生命周期必须到解析完  

catch (rapidxml::parse_error &e) 
{  
//wchar_t *pErr = e.where(); //模版类型老处理不好Ch
printf(“\n===========================\ntest xml ERROR:what-%s\n”, e.what()); //what是char类型
//wprintf(L”ERROR:%s\n”, pErr);
return ;  
}  
}

void test_rapidxml_prase()
{

std::wstring strRow;
std::wstring strName;
std::wstring strTel;
std::wstring strAddr;
std::wstring strTemp;

//解析测试
wprintf(L”\n===========================\ntest xml prase:\n”);

rapidxml::xml_document<wchar_t> doc;

wchar_t  strXml[] = L”<text><row>3</row><row_0><name>wang</name><tel>133xxxx</tel><住址>开北 京</住址></row_0><row_1><name>li</name><tel>135xxxx</tel><住址>西 安?</住址></row_1><row_2><name>zhang</name><tel>137xxxx</tel><住址>太 原2#</住址></row_2></text>”;
//wchar_t  strXml[] = L”<住址>北 京</住址>”;
doc.parse<0>(strXml); //不重新申请内存,会改变参数内容,所以必须使用在解析阶段可用的内存使用

rapidxml::xml_node<wchar_t> * node = doc.first_node(L”text”);

if (node)
{

node = node->first_node(L”row”); //安全使用时可以判断一下返回的node指针是否为空

if (node)
{

strTemp = node->value();
}
}
int iRow = _wtoi(strTemp.c_str());

wprintf(L”ROW:%d\n”, iRow);

rapidxml::xml_node<wchar_t> * node_row = NULL;
for(int i = 0; i < iRow; i++)
{

strRow = stringformat(L”row_%d”, i);
node_row = doc.first_node(L”text”);
if (node_row)
{

node_row = node_row->first_node(strRow.c_str());
strName =  node_row->first_node(L”name”)->value();
strTel = node_row->first_node(L”tel”)->value();
strAddr = node_row->first_node(L”住址”)->value();
}
wprintf(L”ROW_index:%d[name:%s;tel:%s;住址:%s]\n”, i, strName.c_str(), strTel.c_str(), strAddr.c_str());
}

//打印输出
std::wstring sOut;
print(std::back_inserter(sOut), doc, 0);
wprintf(L”doc1:%s\n”, sOut.c_str());

wchar_t cbOut[1024] = {0};
print(cbOut, doc, 0);
wprintf(L”doc2:%s\n”, cbOut);

//std::cout << doc;

//print(std::cout, doc, 0);
}

void test_rapidxml_prase_file_w(char * fileName)
{

//解析测试
wprintf(L”\n===========================\ntest xml prase file:\n”);
std::string strFileName = “c:\\test.xml”;

if (fileName)
{

strFileName = fileName;
}
rapidxml::file<wchar_t> fdoc(strFileName.c_str()); //注意:这里的文件basic_ifstream不支持UTF-16/UNICODE格式,这种文件格式所有字符都使用双字存储,存储空间较大
//只所以不支持UNICODE格式的是因为,文件读入时以二进制读入,一个ansi字符已经被写成0x0031的占用两个字节的16进制,中间加了0;如果再以wchar格式存储,会变为0x0031 0x0000的样子,后面字符串解析出错;而如果以char读入,由于xmlfile中char向量的存储,后面释放内存会出错
rapidxml::xml_document<wchar_t> doc;

wchar_t *strContent = (wchar_t *)fdoc.data();
doc.parse<0>(strContent);//不重新申请内存,会改变参数内容,所以必须使用在解析阶段可用的内存使用

printf(“parse file ok:%s\n”, strFileName.c_str());
rapidxml::xml_node<wchar_t> * node = doc.first_node();
if (node)
{

wprintf(L”node:[name:%s]%s\n”, node->name(), node->value());
}

//打印输出
std::wstring sOut;
print(std::back_inserter(sOut), doc, 0);
//wprintf(L”doc1:%s\n”, sOut.c_str()); //debug
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160870.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • thrift异步调用

    thrift异步调用关于异步,我找了很多资料,java方面的比较多,可c的少之又少,很多就是简单提一下,也么说怎么用,最后终于还是自己研究出来了异步分为服务端异步与客户端异步两部分,理论上他们两者是无关的,不论服务端同步与否,客服端都可以做成异步的。客户端异步客户端异步比较简单,服务端可以使用任何server,TThreadPoolServer或TNonblockingServer等随意,客户端不调用自动

  • 深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件「建议收藏」

    深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件「建议收藏」在求解最优化问题中,拉格朗日乘子法(LagrangeMultiplier)和KKT(KarushKuhnTucker)条件是两种最常用的方法。在有等式约束时使用拉格朗日乘子法,在有不等约束时使用KKT条件。  我们这里提到的最优化问题通常是指对于给定的某一函数,求其在指定作用域上的全局最小值(因为最小值与最大值可以很容易转化,即最大值问题可以转化成最小值问题)。提到KKT条件一般会附带的…

  • UML–活动图详解

    UML–活动图详解活动图活动图是状态机的一个特殊例子,它强调计算过程中的顺序和并发步骤。活动图所有或多数状态都是活动状态或动作状态,所有或大部分的转换都由原状态中完成的活动触发。活动图的含义活动图是一种用于描述系统行为的模型视图,它可用来描述动作和动作导致对象状态改变的结果,而不用考虑引发状态改变的事件。通常,活动图记录单个操作或方法的逻辑、单个用例或商业过程的逻辑流程。在UML中,活动图的起点用来描述活动…

  • onLoad和onShow的使用

    onLoad和onShow的使用onLoad页面第一次加载时执行,只执行一次,一般用于上一级点击进入下一级,需要传参数时使用。onShow除了页面第一次加载时会执行,页面有什么小程序API操作行为也会触发执行。onLoad:function(options){//页面初始化options为页面跳转所带来的参数},onShow:function(){…

  • 页面优化——重绘和回流[通俗易懂]

    页面优化——重绘和回流[通俗易懂]一、写在前面页面优化在面试的过程中经常遇到的问题,今天就来总计一下重绘和回流的问题。二、重绘和回流是什么我们都知道一个页面从加载到完成,首先是构建DOM树,然后根据DOM节点进行几何布局形成render树(渲染树),当渲染树构建完成后,页面就根据DOM树开始布局,渲染树也根据设置的样式渲染这些节点。在这一过程中,比如我们删除DOM节点,修改一个元素的宽高,页面布局发生变化,DOM树也发生变化,那么肯定要重新构建DOm树,而DOM树和渲染树紧密相连,DOM树渲染完了,渲染树也会随之进行渲染,这个过程就

    2022年10月28日
  • route 命令详解

    route 命令详解转自“ITPUB博客”,链接:http://blog.itpub.net/86584/viewspace-755197/因为工作中需要了解网络配置,在众多文中,找到一详解,特此分享。1.使用背景需要接入两个网络,一个是部署环境所在内网环境,这个环境是上不了外网,外网环境很可能是一个无线网络。如果两者都连接上,很可能导致有一方不能起作用,即外网或内网上不了,常常需要…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号