Разбор XML с помощью QXmlStreamReader

Я создал этот XML-файл с QXmlStreamWriter:

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

Я хотел бы создать вектор строки, содержащий все элементы внутри тега Column title="D": теперь я знаю, как создать QVector и как они соответствуют элементам внутри, мне просто нужно выяснить, как я могу это сделать, экстраполируя информацию из xml-файла.

Вы можете помочь мне?


person user3204810    schedule 17.02.2014    source источник
comment
Для более сложного синтаксического анализа xml, подобного этому, вы можете попробовать использовать XQuery из Qt qt-project .org/doc/qt-4.8/xmlprocessing.html. Чтобы использовать их, вам нужно включить xmlpatters в вашем файле .pro (QT += xmlpatterns)   -  person TWE    schedule 17.02.2014


Ответы (2)


Вы можете использовать QXmlStreamReader для перебора элементов XML и поиска элемента <Column title="D">. . Как только вы его найдете, readNextStartElement() в сочетании с skipCurrentElement() можно использовать для чтения всех его дочерних элементов.

Предположим, что документ 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")
person Akira    schedule 23.11.2017

Я бы написал это следующим образом:

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");
}
[..]
person vahancho    schedule 17.02.2014
comment
Этот самый внутренний цикл while выглядит так, как будто он будет зацикливаться вечно в случае ошибки синтаксического анализа. - person Frank Osterfeld; 17.02.2014