So thanks to Huytard I recognized that it is just the behaviour of QXmlStreamReader::readNextStartElement which is somehow unexpected. What I expected was, that it really would just read start elements. And originally I wanted to check beforehand if an element is empty and then decide, what to do with its content. It seems like that is not possible. And that impossibility is covered by the documentation I quoted myself. I.e. even if an atomic element is empty it is virtually followed by a start element which is actually an end element. Thats bad, since you cannot go back in a stream.
Based on his answer I wrote a small example that both clarifies (sorry) and answers my original question.
const QString XML_STR = "<Groups Number=\"4\">" \
"<Group Id=\"0\" GroupName=\"Chambers\">" \
"<MemberChannels>4,5,6,7,8,9,10,11</MemberChannels>" \
"<AverageShown>true</AverageShown>" \
"</Group>" \
"<Group Id=\"1\"/>" \
"<Group Id=\"2\"/>" \
"</Groups>";
int main(int /* argc */, char** /* argv[] */)
{
qDebug() << "the way it would have made sense to me:";
{
QXmlStreamReader reader(XML_STR);
while(!reader.atEnd())
{
reader.readNextStartElement();
QString comment = (reader.isEndElement()) ? "is empty" : "has children";
qDebug() << reader.name() << comment;
}
}
qDebug() << "\napproximation to the way it should probably be done:";
{
QXmlStreamReader reader(XML_STR);
bool gotoNext = true;
while(!reader.atEnd())
{
if(gotoNext) {
reader.readNextStartElement();
}
QString output = reader.name().toString();
reader.readNext();
if(reader.isEndElement()) {
output += " is empty";
gotoNext = true;
} else {
output += " has children";
gotoNext = false;
}
qDebug() << output;
}
}
return 0;
}
which leads to the following output
#they way it would have made sense to me:
"Groups" "has children"
"Group" "has children"
"MemberChannels" "has children"
"MemberChannels" "is empty"
"AverageShown" "has children"
"AverageShown" "is empty"
"Group" "is empty"
"Group" "has children"
"Group" "is empty"
"Group" "has children"
"Group" "is empty"
"Groups" "is empty"
"" "has children"
# this has all been plain wrong
#approximation to the way it should probably be done:
"Groups has children"
"Group has children"
"MemberChannels has children"
" is empty" # ... but not a start element
"AverageShown has children"
" is empty"
"Group has children" # still wrong! this is an end element
"Group is empty"
"Group is empty"
"Groups has children" # ditto
I still don't like it. The way this works I need to triple-check everything which makes the code less readable.