Xử lý tệp XML và XLSX thành bản đồ, hiển thị trong bảng QT

Tệp XML mẫu:

<?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>

Tệp XLSX mẫu:

(Không có nội dung cụ thể)

Kết quả hiển thị bảng:

  • Mở nhiều tệp XML
  • Mở một tệp XML

Chuyển đổi XML thành bản đồ: ProcessXMLFilesToMap

.h

#include <vector>
#include <string>
#include <map>
#include <QFileInfo>
#define CREATE_XLSX // Sử dụng 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 index = 0;
    for (const auto& xmlFile : xmlFiles) {
        ParseXMLToMap(++index, xmlFile, translations);
    }

    return translations;
}

void ParseXMLToMap(int fileIndex, const std::string& xmlFilePath, std::map<int, Translation>& translations) 
{
    QTextCodec *codec = QTextCodec::codecForName("GB2312");
    string selectedFile = codec->fromUnicode(xmlFilePath.c_str()).data();
    std::ifstream file(selectedFile.c_str());
    if (!file.is_open()) {
        std::cerr << "Lỗi mở tệp: " << 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()) {
                        translations[currentId].texts.insert(translations[currentId].texts.end(), currentTexts.begin(), currentTexts.end());
                    } else {
                        Translation translation;
                        translation.label = currentLabel;
                        while(translation.texts.size() < (fileIndex - 1)) {
                            translation.texts.push_back("");
                        }
                        translation.texts.insert(translation.texts.end(), currentTexts.begin(), currentTexts.end());
                        translations[currentId] = translation;
                    }
                }
                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.insert(translations[currentId].texts.end(), currentTexts.begin(), currentTexts.end());
        } else {
            Translation translation;
            translation.label = currentLabel;
            while(translation.texts.size() < (fileIndex - 1)) {
                translation.texts.push_back("");
            }
            translation.texts.insert(translation.texts.end(), currentTexts.begin(), currentTexts.end());
            translations[currentId] = translation;
        }
    }

    file.close();
    if(fileIndex > 1)
        CompleteMissingTexts(fileIndex, translations);
}

void CompleteMissingTexts(int fileIndex, std::map<int, Translation>& translations)
{
    for (auto& pair : translations)
    {
        Translation *translation = &pair.second;
        while(translation->texts.size() < fileIndex) {
            translation->texts.push_back(translation->texts[0]);
        }
    }
}

Thao tác bảng QT với tệp 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();
};

Thao tác bảng QT với tệp 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);
    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);
}

Thẻ: XML parsing C++ Qt XLSX map data structure

Đăng vào ngày 11 tháng 6 lúc 05:20