316_C++_xml文件解析成map,可以放到QT表格上, 且 xml、xlsx文件可以互相解析

news2024/9/23 15:27:42

xml文件例如:

在这里插入图片描述<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <TrTable> <tr id="0" label="TR_PB_CH" text="CH%2"/> <tr id="4" label="TR_PB_CHN" text="Channel"/> <tr id="5" label="TR_PB_WARNING" text="Warning!"/> <tr id="6" label="TR_PB_NOTICE" text="Notice"/> <tr id="7" label="TR_PB_DEFAULT" text="Default"/> <tr id="8" label="TR_PB_SAVE" text="Save"/> <tr id="17" label="TR_PB_CLEAR" text="add-left1"/> <tr id="18" label="TR_PB_ALL" text="add-left2"/> <tr id="19" label="TR_PB_CLEAR-2" text="add-left3"/> <tr id="20" label="TR_PB_ALL-2" text="add-left4"/> <tr id="21" label="TR_PB_ALL-2" text="add-left4"/> <tr id="150524" label="TR_IPC_ACTIVE_PASSWD_MODE2" text="add-left5"/> </TrTable>

xlsx文件例如:

在这里插入图片描述

表格显示效果:

在这里插入图片描述:多个xml文件打开


在这里插入图片描述
:单个xml文件打开

xml文件解析成map:ProcessXMLFilesToMap

-------------------------------.h-------------------------------
#include <vector>
#include <string>
#include <map>
#include <QFileInfo>
#define CREATE_XLSX // 采用xlsx
using namespace std;
struct Translation {
    string label;
    vector<string> texts;
};

struct TextsInfo {
	int id;
    string label;
    string text;
};
-------------------------------.cpp-------------------------------
std::map<int, Translation> ProcessXMLFilesToMap(std::vector<std::string>& xmlFiles)
{
    std::map<int, Translation> translations;
    int num = 0;
    for (const auto& xmlFile : xmlFiles) {
        ParseXMLToMap(++num, xmlFile, translations);
    }

    return translations; //返回给表格所需的map
}

// 解析XML文件并填充translations map
void ParseXMLToMap(int fileNum, const std::string& xmlFilePath, std::map<int, Translation>& translations) 
{
    QTextCodec *code = QTextCodec::codecForName("GB2312"); //上层,转成中文后,可以解析使用中文路径
    string selectedFile = code->fromUnicode(xmlFilePath.c_str()).data();
    std::ifstream file(selectedFile.c_str());
    if (!file.is_open()) {
        std::cerr << "Error opening file: " << xmlFilePath << std::endl;
        return;
    }

    std::string line;
    bool inTrTag = false;
    std::string currentLabel;
    std::vector<std::string> currentTexts;
    int currentId = -1;

    while (std::getline(file, line)) {
        if (!line.empty() || line[0] == '<') {
            if (inTrTag) {
                if (currentId != -1) {
					if (translations.find(currentId) != translations.end()) 
					{	
						// 该ID存在在map中,就进行当前位置的插入
						translations[currentId].texts.insert(translations[currentId].texts.end(), currentTexts.begin(), currentTexts.end());
                    }
					else 
					{
						// 该ID不存在在map中,就进行尾部的插入
						Translation translation;
						translation.label = currentLabel;
						while(translation.texts.size() < (fileNum - 1))
						{
							translation.texts.push_back("");
						}
						translation.texts.insert(translation.texts.end(), currentTexts.begin(), currentTexts.end());
						translations[currentId] = translation;
					}
                }
                // 一轮赋值完毕,这些用了暂时保存数据的变量、容器就要clear清空,方便下次继续
                inTrTag = false;
                currentLabel.clear();
                currentTexts.clear();
                currentId = -1;
            }
            // 开始逐行解析
            size_t trPos = line.find("<tr");
            if (trPos != std::string::npos) {
                size_t idPos = line.find("id=\"", trPos);
                size_t labelPos = line.find("label=\"", trPos);
                size_t textPos = line.find("text=\"", trPos);

                if (idPos != std::string::npos && labelPos != std::string::npos && textPos != std::string::npos) {
                    std::string idStr = line.substr(idPos + 4, line.find('"', idPos + 4) - idPos - 4);
                    std::string labelStr = line.substr(labelPos + 7, line.find('"', labelPos + 7) - labelPos - 7);
                    std::string textStr = line.substr(textPos + 6, line.find("/>", textPos + 6) - textPos - 6);
                    while(!textStr.empty() && textStr.back() != '\"')
                        textStr.pop_back();

                    if(!textStr.empty())
                        textStr.pop_back();
						

                    currentId = std::stoi(idStr);
                    currentLabel = labelStr;
                    currentTexts.push_back(textStr);
                    inTrTag = true;
                }
            }
        }
		else if (inTrTag) 
		{
            currentTexts.push_back(line);
        }
    }

    if (inTrTag && currentId != -1) 
	{
	    if (translations.find(currentId) != translations.end()) 
		{	
	        //translations[currentId].texts.push_back(currentTexts);	
			translations[currentId].texts.insert(translations[currentId].texts.end(), currentTexts.begin(), currentTexts.end());
	    } 
		else 
		{
	        Translation translation;
	        translation.label = currentLabel;
			while(translation.texts.size() < (fileNum - 1))
			{
				translation.texts.push_back("");
			}
			
			translation.texts.insert(translation.texts.end(), currentTexts.begin(), currentTexts.end());
	        translations[currentId] = translation;
	    }
    }

    file.close();
	if(fileNum > 1) // 多个文件,就依照第一个文件的ID作为依据,拼接后续文件的text而已
		CompleteMissingTexts(fileNum, translations);	
}

void CompleteMissingTexts(int fileNum, std::map<int, Translation>& translations)
{
    for (auto& pair : translations)
    {
		Translation *translation = &pair.second;

		while(translation->texts.size() < fileNum)
		{
			translation->texts.push_back(translation->texts[0]);
		}
	}
}

-------------------------------QT表格xml打开操作.h-------------------------------
class xmlFileDoc : public FileDoc // 继承自自写类
{
    Q_OBJECT
public:
    explicit xmlFileDoc(QWidget *parent);
    ~xmlFileDoc();
    void openFile(QString& aFileName); //打开文件
    void openFiles(std::vector<std::string>& FileNames);
    void refreshTable(std::map<int, Translation> trans);
    void closeEvent(QCloseEvent *event);
    void saveFile();
    std::vector<TextsInfo> textVectorInfos();
};
-------------------------------QT表格xml打开操作.cpp-------------------------------
void xmlFileDoc::openFiles(std::vector<std::string>& FileNames)
{
	m_type = MUL_XML_FILE;
    m_files = FileNames;
    std::map<int, Translation> trans = ProcessXMLFilesToMap(FileNames);
    refreshTable(trans);
	m_customTableWidget->setFileType(false);
}

void xmlFileDoc::refreshTable(std::map<int, Translation> trans)
{
    if (m_files.size() == 0)
    {
        return;
    }
    QSignalBlocker blocker(m_customTableWidget);// 阻塞表格其他地方的信号,例如itemchanged信号
    m_customTableWidget->setRowCount(trans.size());
    m_customTableWidget->setColumnCount(m_files.size()+2);
    m_customTableWidget->setRestrictedColumns(m_files.size()+2);

    QStringList horizontalHeaderLabels;
    horizontalHeaderLabels << "ID" << "Label";

    for (int i = 0; i < m_files.size(); i++)
    {
        std::string filename = extractFileName(m_files[i]);
        horizontalHeaderLabels << filename.c_str();
    }

    m_customTableWidget->setHorizontalHeaderLabels(horizontalHeaderLabels);

    int row = 0;
    for (auto &pair : trans)
    {
        int col = 0;
        QTableWidgetItem *item;
        item = new QTableWidgetItem(QString::number(pair.first));
        m_customTableWidget->setItem(row,col++,item);
        item = new QTableWidgetItem(QString::fromStdString(pair.second.label));
        m_customTableWidget->setItem(row,col++,item);
        for (int num = col; num < m_files.size()+2; num++)
        {
            item = new QTableWidgetItem(QString::fromStdString(pair.second.texts[num - 2]));
            m_customTableWidget->setItem(row,num,item);
        }
        row++;
    }
}

void xmlFileDoc::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1596379.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

新专业探路:智能视觉工程专业实验室如何建?

今日&#xff0c;“第八届全国高校电子信息类专业教学论坛”在成都圆满闭幕。整体会议聚焦人才自主培养、一流专业建设、新质课程建设&#xff0c;来自全国多所高校和企业的参会代表齐聚一堂&#xff0c;分享教育与教学成果为推动电子信息类专业建设及课程建设&#xff0c;探讨…

指针的深入理解(七)

指针的深入理解&#xff08;七&#xff09; 个人主页&#xff1a;大白的编程日记 个人专栏&#xff1a;C语言学习之路 感谢遇见&#xff0c;我们一起学习进步&#xff01; 文章目录 指针的深入理解&#xff08;七&#xff09;前言一.常量字符串指针1.1常量字符串的理解1.2常量…

UDTF函数 explode

场景&#xff1a; 原hive数据形式 split 处理到一个Array 形式 使用explode炸开后的效果是 explode结合侧面视图达到targeType 目标形式&#xff1a; 一进多出 explode 将hive 中复杂的 array 炸成多行 因为炸开后&#xff0c; movie 列值少于categoryname 列所以这里为了达到…

如何使用Python曲线拟合

在Python中进行曲线拟合通常涉及使用科学计算库&#xff08;如NumPy、SciPy&#xff09;和绘图库&#xff08;如Matplotlib&#xff09;。下面是一个简单的例子&#xff0c;演示如何使用多项式进行曲线拟合&#xff0c;在做项目前首先&#xff0c;确保你已经安装了所需的库。 1…

宝宝洗衣机怎么选?四款畅销卓越婴儿洗衣机深度剖析!

近几年科技高速发展&#xff0c;我们的生活也因此变得更加便捷、健康高效。尤其是在家庭生活中&#xff0c;各种新兴家电的出现让我们的生活变得更加健康卫生。婴儿洗衣机也为现代家庭提供了极大的便捷。由于婴儿刚出生免疫力比较弱&#xff0c;所以建议婴儿的衣物尽量和大人的…

10分钟1000台虚机 云安全效能双升 亚信安全新信舱无代理云平台快速适配版正式发布

新信舱 亚信安全新信舱无代理云平台快速适配版正式发布。在云平台依赖性、无代理部署速度、宿主机无代理AV防护和虚拟机缓存扫描性能等方面&#xff0c;新信舱无代理版本提供了无缝的可扩展性、低资源消耗并降低管理复杂性&#xff0c;让安全防护真正做到了 多快好省&#xff…

Spring Boot 整合 Mockito:提升Java单元测试的高效实践

引言 在Java开发领域&#xff0c;Spring Boot因其便捷的配置和强大的功能而受到广泛欢迎&#xff0c;而Mockito作为一款成熟的单元测试模拟框架&#xff0c;则在提高测试质量、确保代码模块间解耦方面扮演着至关重要的角色。本文将详细介绍如何在Spring Boot项目中整合Mockito&…

天府锋巢运营方树莓集团——全国园区赋能,助力企业开源节流

树莓集团&#xff0c;作为天府锋巢直播产业基地的运营方&#xff0c;一直在数字产业生态链的建设中走在行业前列。不同于传统的园区或商管公司&#xff0c;树莓集团不仅为企业提供物理入驻空间&#xff0c;更是创造了高效、多维度、多渠道的无边界产业办公体验。这种独特的运营…

第四百五十四回

文章目录 1. 问题描述2. 优化方法2.1 缩小范围2.2 替代方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取AppBar的高度"相关的内容&#xff0c;本章回中将介绍关于MediaQuery的优化.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 问题描述 我们在…

package.java文件的作用

你查看springboot的源码&#xff0c;有很多类都有这个文件&#xff0c;在idea不能创建&#xff0c;因为不支持这种命名&#xff0c;只能用记事本创建后复制都项目中。 主要应用是给类添加正常&#xff0c;或者把公用的注解都放到这里&#xff0c;常量不合适&#xff0c;作用范…

爬虫机试题-爬取新闻网站

之前投简历时遇到了这样的一个笔试。本以为会是数据结构算法之类的没想到直接发了一个word直接提需求&#xff0c;感觉挺有意思就写了这篇文章&#xff0c;感兴趣的朋友可以看看。 拿到urllist 通过分析页面结构我们得以知道&#xff0c;这个页面本身没有新闻信息&#xff0c;是…

夜月一帘幽梦,春风十里“三指针法“ (链表面试题篇2)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…

Gemini国内怎么使用

GPT、Claude、Gemini全系列模型国内使用方法来了&#xff01; 一直以来很多人问我能不能有个稳定&#xff0c;不折腾的全球AI大模型测试网站&#xff0c;既能够保证真实靠谱&#xff0c;又能够保证稳定、快速&#xff0c;不要老动不动就挂了、出错或者漫长的响应。 到目前为止…

深度学习入门(3)

一、感知机 感知机接收多个输入信号&#xff0c;输出一个信号。这里所说的“信号”可以想象成电流或河流那样具备“流动性”的东西。 但是&#xff0c;和实际的电 流不同的是&#xff0c;感知机的信号只有“流 / 不流”&#xff08; 1 / 0 &#xff09;两种取值。在本书中&…

FFmpeg: 自实现ijkplayer播放器--03UI界面设计

文章目录 UI设计流程图UI设计界面点击播放功能实现 UI设计流程图 UI设计界面 主界面 控制条 播放列表 画面显示 标题栏 设置界面 提示框 点击播放功能实现 槽函数实现&#xff1a; connect(ui->ctrlBarWind, &CtrlBar::SigPlayOrPause, this, &Main…

vue表格操作列,按钮太多显示... 点击后悬浮显示全部按钮

效果: 分析原理: 一共就三步,仔细看看很简单,位置要加对,代码结构下边有demo 代码结构demo: <el-table-columnlabel"操作"align"center"fixed"right"show-overflow-tooltip><template slot-scope"scope"><el-buttonsi…

绿色地狱steam叫什么 绿色地狱steam怎么搜

绿色地狱steam叫什么 绿色地狱steam怎么搜 《绿色地狱》是一款以亚马逊雨林为背景的开放世界生存模拟游戏。玩家们扮演一名被困在丛林中的冒险者&#xff0c;玩家在游戏内需要学习采集资源、建造庇护所、狩猎和烹饪食物&#xff0c;同时要面对丛林中的危险和挑战&#xff0c;…

Java入门学习Day05

本篇文章主要有创建package、关系运算符、逻辑运算符、三元运算符和其对应的实例。 一、创建package 创建一个包&#xff0c;把我们之前或之后用到的运算符代码都放到这个package里&#xff0c;方面管理。 包的命名通常是公司的网站名称倒着写(com.mayin)&#xff0c;再加上…

简析|抖音隋总分享的人力RPO项目怎么样?

在抖音这个充满活力和创新的平台上&#xff0c;隋总以其独到的见解和深刻的行业洞察&#xff0c;吸引了众多粉丝的关注。最近&#xff0c;隋总分享的人力RPO项目引起了广泛关注&#xff0c;那么&#xff0c;这个项目究竟怎么样呢? 首先&#xff0c;人力RPO&#xff0c;即招聘流…

前端开发攻略---JS将class转换为function。满分写法无死角

1、class写法 class Example {constructor(name) {this.name name}func() {console.log(this.name)}} 2、function写法 use strictfunction Example(name) {if (!new.target) {throw new TypeError(Class constructor Example cannot be invoked without new)}this.name name…