c++ - 如何让xml解析器更清晰

标签 c++ xml qt

我有一个以这种方式构建的 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Draw>
    <Input>
        <Cells>
            <width>100</width>
            <height>28</height>
        </Cells>
        <Column>custom</Column>
        <Custom>
            <header id="0">one</header>
            <header id="1">two</header>
            <header id="2">three</header>
            <header id="3">four</header>
            <header id="4">five</header>
        </Custom>
    </Input>
 <Output>
        <Cells>
            <width>82</width>
            <height>20</height>
        </Cells>
        <Column>upper</Column>
        <Custom>
            <header id="0">alfa</header>
            <header id="1">beta</header>
            <header id="2">gamma</header>
            <header id="3">delta</header>
            <header id="4">epsilon</header>
        </Custom>
    </Output>
</Draw>

我正在尝试推断 header 标签的值:因为我们有两组 header 标签(输入和输出),我现在设法工作的唯一工作代码是:

void MainWindow::readXmlFile() {
    QString target;
    QFile* file = new QFile("System/Settings.xml");
    /* If we can't open it, let's show an error message. */
    if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) return;
    QXmlStreamReader xmlReader(file);
    /* We'll parse the XML until we reach end of it.*/
    while(!xmlReader.atEnd() && !xmlReader.hasError()) {
        QXmlStreamReader::TokenType token = xmlReader.readNext();
        if(token == QXmlStreamReader::StartDocument) {
            continue;
        }
        /* If token is StartElement, we'll see if we can read it.*/
        if (token == 4) {
            if (xmlReader.name() == "Input" || xmlReader.name() == "Output") {
                target = xmlReader.name().toString();
                while (!(xmlReader.tokenType() == QXmlStreamReader::EndElement && xmlReader.name() == target)) {
                    if (xmlReader.tokenType() == QXmlStreamReader::StartElement) {
                        qDebug() << xmlReader.name().toString();
                        if (xmlReader.name() == "width") {
                            QString num = xmlReader.readElementText();
                            //input->horizontalHeader()->setDefaultSectionSize(num.toInt());
                        }
                        if (xmlReader.name() == "height") {
                            QString num = xmlReader.readElementText();
                            //input->verticalHeader()->setDefaultSectionSize(num.toInt());
                        }
                        if (xmlReader.name() == "header") {
                            //headers->append(xmlReader.readElementText());
                            //qDebug() << xmlReader.readElementText();
                        }
                        //input->setHorizontalHeaderLabels(header);
                    }
                    xmlReader.readNext();
                }

            }
        }
    }
    /* Error handling. */
    if(xmlReader.hasError()) {
        QMessageBox::critical(this,
                              "QXSRExample::parseXML",
                              xmlReader.errorString(),
                              QMessageBox::Ok);
    }
    xmlReader.clear();
}

由于这段代码看起来非常重复,尤其是从第 15 行到第 18 行,你能帮我把它写得更干净一点吗?网络中的示例不是很清楚。

提前致谢

最佳答案

我通常使用 lambda 表达式。您需要将 CONFIG += c++11 添加到您的 .pro 文件中。 然后为大多数重复模式定义实用程序:例如

    /* If token is StartElement, we'll see if we can read it.*/
    if (token == 4) {
        auto name = [&]() { return xmlReader.name().toString(); };
        auto type = [&]() { return xmlReader.tokenType(); };
        auto num = [&]() { return xmlReader.readElementText().toInt(); };
        if (name() == "Input" || name() == "Output") {
            target = name();
            while (!(type() == QXmlStreamReader::EndElement && name() == target)) {
                if (type() == QXmlStreamReader::StartElement) {
                    qDebug() << name();
                    if (name() == "width") {
                        input->horizontalHeader()->setDefaultSectionSize(num());
                    }
                    else if (name() == "height") {
                        input->verticalHeader()->setDefaultSectionSize(num());
                    }
                    else if (name() == "header") {
                        //headers->append(xmlReader.readElementText());
                        //qDebug() << xmlReader.readElementText();
                    }
                    //input->setHorizontalHeaderLabels(header);
                }
                xmlReader.readNext();
            }
        }

不相关的警告:您的代码正在泄漏内存,而不是使用 new 进行分配,考虑更简单的堆栈分配:

QFile file("System/Settings.xml");
/* If we can't open it, let's show an error message. */
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
QXmlStreamReader xmlReader(&file);

关于c++ - 如何让xml解析器更清晰,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24618957/

相关文章:

qt - graph_tool pyside gtk 2.x 和 gtk 3.x

c++ - 如何启动具有 root 权限的 QProcess?

c++ - 如何使 QGraphicsTextItem 可点击?

c++ - 无法在 C++ 中为全局数组赋值

android - 使用 Android NDK 编译 Boost 时 assert.h 冲突

c++ - 调用 glComputeDispatch 后 OpenGL 计算着色器过早中止

java - 元素名称已使用简单框架

c++ - 将一行二维数组分配给一维数组

xml - 如何防止 JSON Web 服务响应下载到文件?

java - 将 PDF 转换为 XML-XSL - Java?