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