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);
}