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

65 篇文章 7 订阅
文章讲述了如何解析XML文件,将其内容转换为Qt中的map结构,并应用到一个表格视图中,展示了从多个XML文件中提取数据并整合到一个表格中的过程。
摘要由CSDN通过智能技术生成

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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扳手的海角

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值