解决方案

RapidXml读取并修改XML文件

seo靠我 2023-09-26 00:28:51

RapidXml读取并修改XML文件

RapidXml介绍RapidXml读取与修改xml文件

RapidXml介绍

RapidXml尝试创建最快的XML解析器,同时保留可用性,可移植性和合理的W3C兼容性SEO靠我。它是一个用现代C ++编写的原位解析器,解析速度接近strlen在同一数据上执行的函数。它仅仅只由四个头文件组成,并不要单独进行配置编译,使用起来非常方便。

在RapidXml的官网上,它发布了与其他SEO靠我xml解析库的速度对比,应该可以说RapidXml是目前最快的xml解析器。

RapidXml通过使用以下几种技术实现了它的速度:

1,原位解析。构建DOM树时,RapidXml不会复制字符串数据,例如节SEO靠我点名称和值。相反,它存储指向源文本内部的指针。

2,使用模板元编程技术。这允许它将大部分工作转移到编译时。通过模板的魔力,C ++编译器为您使用的任何解析器标志组合生成解析代码的单独副本。在每个副本中,SEO靠我所有可能的决定都在编译时进行,并且省略所有未使用的代码。

3,广泛使用查找表进行解析。

4,手动调优的C ++,在几个最流行的CPU上进行了分析。

RapidXml读取与修改xml文件

我们以下面这个xml为SEO靠我例,找到key值为"ReportIndex"的节点,并在这个节点前面插入一个新的节点"",同时将key值为"ReportIndex"的节点以及后面的节点的offset值都加上4。

<hsbinmsg lSEO靠我imit_size="5096" note="hsbinmsg msgtype info"><head note="packet head"><field key="msgtype" type="6"SEO靠我 offset="0"/><field key="bodylength" type="6" offset="4"/></head><tail note="packet tail"><field keySEO靠我="checksum" type="6" offset="-1"/></tail><msgtype id="202098" name="DesignationReport(202098)"><dataSEO靠我set note=""><field key="ReportIndex" type="7" offset="12" size="8"/><field key="app1id" type="17" ofSEO靠我fset="20" size="3"/></dataset></msgtype> </hsbinmsg>

     CXmlParse解析类的头文件如下:

#pragma once SEO靠我#include "rapidxml.hpp" #include "rapidxml_utils.hpp" #include "rapidxml_print.hpp" SEO靠我 #include <string>#define XML_NODE_NAME "msgtype" #define XML_NODE_NAME2 "ReportIndexSEO靠我"#define OFFSET_SIZE 4class CXmlParse { public:CXmlParse(const std::string &strPath)SEO靠我;~CXmlParse();private:int LoadXml();//找到key为name的属性bool GetAttrByName(const char* name, rapidxml::xmSEO靠我l_node<>* pNode, rapidxml::xml_attribute<> *&pAttr);void UpdateAtributeValue(rapidxml::xml_document<SEO靠我> &doc, rapidxml::xml_attribute<>* &pAttr, int nOffset);void MakeFileCopy(const std::string& strPathSEO靠我);private:std::string m_strPath;std::string m_strNewPath; };

     cpp实现文件:

#include "XmlParse.h" SEO靠我 #include <windows.h> #include <iostream>CXmlParse::CXmlParse(const std::string &strPatSEO靠我h) {m_strPath = strPath;MakeFileCopy(m_strPath);if (LoadXml()){std::cout << "XML处理成功" << stdSEO靠我::endl;}else{std::cout << "XML处理失败" << std::endl;} }CXmlParse::~CXmlParse() {}//加载xmSEO靠我l int CXmlParse::LoadXml() {if (m_strPath.empty()){return -1;}try{rapidxml::file<> fSEO靠我ile(m_strPath.c_str());rapidxml::xml_document<> doc;doc.parse<0>(file.data());//根节点rapidxml::xml_nodSEO靠我e<>* root = doc.first_node();rapidxml::xml_node<>* pNode = root->first_node();while (pNode) //第二层节点hSEO靠我ead,msgtype{std::string strName = pNode->name();if (strName.compare(XML_NODE_NAME) == 0) //找到msgtypeSEO靠我{rapidxml::xml_node<>* pNode2 = pNode->first_node(); //第三层节点datasetif (pNode2){rapidxml::xml_node<>*SEO靠我 pNode3 = pNode2->first_node(); //第四层节点field,只找第一个bool bFind = false;rapidxml::xml_attribute<> *attrSEO靠我;if (GetAttrByName("key", pNode3, attr)){if (strcmp(attr->value(), "ReportIndex") == 0){bFind = trueSEO靠我;}}if (bFind){//遍历第四层节点field节点, offset偏移量+4while (pNode3){rapidxml::xml_attribute<> *attrSize;GetAttSEO靠我rByName("offset", pNode3, attrSize);UpdateAtributeValue(doc, attrSize, OFFSET_SIZE);pNode3 = pNode3-SEO靠我>next_sibling();}//只要找到了一个key="ReportIndex"的field,那么就需要新插入一个noderapidxml::xml_node<> *pNewNode = docSEO靠我.allocate_node(rapidxml::node_element, "field");if (pNewNode){pNewNode->append_attribute(doc.allocatSEO靠我e_attribute("key", "PartitionNo"));pNewNode->append_attribute(doc.allocate_attribute("type", "6"));pSEO靠我NewNode->append_attribute(doc.allocate_attribute("offset", "8"));pNewNode->append_attribute(doc.alloSEO靠我cate_attribute("size", "4"));pNode2->prepend_node(pNewNode);}}}}pNode = pNode->next_sibling();}std::SEO靠我ofstream out(m_strNewPath);out << doc;out.close(); return 1;}catch (...){std::cout << "XML解析出现异常" <<SEO靠我 std::endl;return -1;} }//获取到节点中key为name的属性 bool CXmlParse::GetAttrByName(const charSEO靠我* name, rapidxml::xml_node<>* pNode, rapidxml::xml_attribute<> *&pAttr) {if (pNode == NULL)rSEO靠我eturn false;for (rapidxml::xml_attribute<> *attr = pNode->first_attribute(); attr; attr = attr->nextSEO靠我_attribute()){if (strcmp(attr->name(), name) == 0){pAttr = attr;return true;}}return true; }SEO靠我//更新属性的值 void CXmlParse::UpdateAtributeValue(rapidxml::xml_document<> &doc, rapidxml::xml_atSEO靠我tribute<>* &pAttr, int nOffset) {if (NULL == pAttr)return;const char* oldValue = pAttr->valuSEO靠我e();int nValue = atoi(oldValue);nValue += nOffset;char str[12];memset(str, 0, 12);_itoa_s(nValue, stSEO靠我r, 10);pAttr->value(doc.allocate_string(str), strlen(str)); }//根据原路径得到新路径(原路径名+“2”) SEO靠我void CXmlParse::MakeFileCopy(const std::string& strPath) {std::string strNewPath = strPath;iSEO靠我nt nPos = strNewPath.find_last_of(".");if (nPos != std::string::npos){std::string strTemp = strNewPaSEO靠我th.substr(nPos + 1);strNewPath = strNewPath.substr(0, nPos);strNewPath += "2.";strNewPath += strTempSEO靠我;m_strNewPath = strNewPath;} }

RapidXml遍历节点跟TinyXml遍历节点的方式一样,都是先获取根节点,然后获取到根节点下方的first_node()SEO靠我,然后通过next_sibling()不停地指向下一个兄弟节点,同时兄弟节点也可以深度去遍历。获取节点的各个属性值也是一样的使用方式。

本程序为了和原xml文件作对比,就创建了新的文件,如果想在原文件上SEO靠我做修改,直接将std::ofstream out(m_strNewPath);中的m_strNewPath替换为m_strPath即可。

类封装好后,调用也非常方便。CXmlParse parse(stSEO靠我rPath);

     附上完整例子代码:Demo

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2