Question

I created this xml file with 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>

I would like to create a Vector of String containing all the items inside the tag Column title="D": Now, I know how to create a QVector and how they fit elements on the inside, I just have to figure out how I can do this by extrapolating information from an xml file.

Can you help me?

No correct solution

OTHER TIPS

You can use the QXmlStreamReader to iterate through the XML elements and find the <Column title="D"> element. Once you found it, the readNextStartElement() in combination of skipCurrentElement() can be used to read its all child elements.

Let's assume that the XML document you shown in your examle can be read from the xmlDocument object. To extract all <item> elements from <Column title="D"> element with appropriate error checking, you can do the following:

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;

In the example above I used two predicates to hide the long and hardly readable validation of xmlIterator. These are the following:

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");
}

Sample result:

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

I would write it in the following way:

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");
}
[..]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top