如何使xml解析器更清晰

时间:2014-07-07 20:10:03

标签: 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>

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

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行,您能帮助我让它变得更干净吗?网络上的例子不太清楚。

提前致谢

2 个答案:

答案 0 :(得分:1)

我通常使用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);

答案 1 :(得分:1)

几周前我遇到了同样的问题,我不得不读写一些xml文件(arround 20/50行)。

我从QXmlStreamReader / Writer开始,最后放弃并使用QDomDocument。

这两个对象之间的主要区别(在性能方面)是QDomDocument将所有xml文件加载到内存中。使用QDomDoc语法也很容易!

请参阅文档以获取一些书面示例:http://qt-project.org/doc/qt-4.8/qdomdocument.html