使用 QXmlStreamReader 解析 XML

Parse XML with QXmlStreamReader

提问人:user3204810 提问时间:2/17/2014 最后编辑:Akirauser3204810 更新时间:11/23/2017 访问量:2141

问:

我使用 QXmlStreamWriter 创建了这个 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<Draw>
    <Input>
        <Column title="A"/>
        <Column title="B"/>
        <Column title="C"/>
        <Column title="D">
            <item id="0">Bayer Leverkusen</item>
            <item id="1">Benfica</item>
            <item id="2">Villareal</item>
            <item id="3">Montpellier</item>
        </Column>
    </Input>
</Draw>

我想创建一个包含标签内所有项目的字符串向量:现在,我知道如何创建一个以及它们如何适合内部的元素,我只需要弄清楚如何通过从 xml 文件中推断信息来做到这一点。Column title="D"QVector

你可以帮我吗?

C++ QT QSrek QCyT QMata QXMLTroReader

评论

0赞 TWE 2/17/2014
对于像这样更复杂的xml解析,您可以尝试在Qt qt-project.org/doc/qt-4.8/xmlprocessing.html 中使用XQuerys。要使用它们,您需要在 .pro 文件中启用 xmlpatters (QT += xmlpatterns)

答:

-1赞 vahancho 2/17/2014 #1

我会这样写:

QVector<QString> store;

[..]
if (reader.readNextStartElement() && reader.name() == "Draw") {
    while (reader.readNextStartElement() && reader.name() == "Input") {
        while (reader.readNextStartElement()) {
            QXmlStreamAttributes attr = reader.attributes();
            if (reader.name() == "Column" && attr.value("title").toString() == "D") {
                while(!(reader.isEndElement() && reader.name() == "Column")) {
                    if (reader.isStartElement() && reader.name() == "item") {
                        QString text = reader.readElementText();
                        store.append(text);
                    }
                    reader.readNext();
                    if (reader.hasError()) {
                        // Handle error.
                        QString msg = reader.errorString();
                        break;
                    }
                }
            } else {
                reader.readNext();
            }
        }
    }
} else {
    reader.raiseError("Expected <Draw> element");
}
[..]

评论

0赞 Frank Osterfeld 2/17/2014
那个最里面的 while 循环看起来会永远循环,以防出现解析错误。
0赞 Akira 11/23/2017 #2

可以使用 QXmlStreamReader 循环访问 XML 元素并查找该元素。找到它后,readNextStartElement() 与 skipCurrentElement() 的组合可用于读取其所有子元素。<Column title="D">

假设可以从对象中读取您在考试中显示的 XML 文档。要通过适当的错误检查从元素中提取所有元素,您可以执行以下操作:xmlDocument<item><Column title="D">

QXmlStreamReader xmlIterator(xmlDocument);
QVector<QString> output;

for(; !xmlIterator.atEnd(); xmlIterator.readNext()) {
    if(isStartElementOfColumnD(xmlIterator)) {
        while(xmlIterator.readNextStartElement()) {
            if(isItemElement(xmlIterator))
                output.append(xmlIterator.readElementText());
            else
                xmlIterator.skipCurrentElement();
        }
    }
}

if(xmlIterator.hasError())
    qCritical() << "Error has occurred:" << xmlIterator.errorString();
else
    qDebug() << output;

在上面的示例中,我使用了两个谓词来隐藏 的冗长且难以阅读的验证。具体如下:xmlIterator

inline bool isStartElementOfColumnD(const QXmlStreamReader& xmlIterator) {
    return xmlIterator.isStartElement() && xmlIterator.name() == "Column" &&
            xmlIterator.attributes().value("title") == "D";
}
inline bool isItemElement(const QXmlStreamReader& xmlIterator) {
    return xmlIterator.name() == "item" &&
            xmlIterator.attributes().hasAttribute("id");
}

示例结果:

QVector("Bayer Leverkusen", "Benfica", "Villareal", "Montpellier")