Не удается идентифицировать пустые элементы с помощью QXmlStreamReader

У меня возникли проблемы с обнаружением пустых элементов с использованием Qt QXmlStreamReader (Qt 4.8.1).
Существует файл XML, который имеет следующий раздел

<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" GroupName="Fluids">
<MemberChannels>0,1,17,18</MemberChannels>
<AverageShown>false</AverageShown>
</Group>
<Group Id="2"/>
<Group Id="3"/>
</Groups>

Как видите, элементы с Id 2 и 3 пусты, кроме атрибута. Атрибут ничего не меняет. Если это не в элементе, проблема все еще возникает.

Это код синтаксического анализа с использованием QXmlStreamReader, я упростил его, поэтому он может не скомпилироваться. Просто у вас есть основная идея.

[...]
QXmlStreamReader* m_poStreamReader = new QXmlStreamReader;
[...]

if(m_poStreamReader->readNextStartElement() && m_poStreamReader->name().toString() == "Group") {
this->parseGroupElement();
}

[...]

bool CTempscanXmlParser::parseGroupElement( void ) {
TGroupElement tElement;
if(m_poStreamReader->isStartElement() && !m_poStreamReader->isEndElement()) { // not empty
TGroupElement tElement = this->readGroupElement();
} else if(m_poStreamReader->isStartElement() && m_poStreamReader->isEndElement()) { // empty
tElement.oGroupName = QString::null;
}
[...]
}

В документации сказано:

Пустые элементы также сообщаются как StartElement, за которыми непосредственно следует EndElement.

Я могу использовать readNext () и до сих пор не получить конечный элемент. Кажется, что парсер может только обнаружить

<tag></tag>

как пустой элемент, но не

<tag/>

Так это только у меня или проблема существует в Qt? И если так, как я могу обнаружить пустые элементы, которые не состоят из 2 отдельных элементов (начало / конец)?

Редактировать:
Итак, Хейтард попросил у меня рабочий пример. Но его ответ привел меня к решению, которое почти ответило на мой вопрос. Поэтому я привел разъясненный пример в своем ответе.

1

Решение

Так что благодаря Хейтарду я понял, что это просто поведение QXmlStreamReader :: readNextStartElement, которое как-то неожиданно. Я ожидал, что это будет просто читать Начните элементы. И изначально я хотел заранее проверить, является ли элемент пустым, а затем решить, что делать с его содержимым. Кажется, что это невозможно. И эта невозможность покрыта документацией, которую я сам цитировал. То есть даже если атомарный элемент пуст, за ним фактически следует начальный элемент, который фактически является конечным элементом. Это плохо, так как вы не можете вернуться в поток.

Основываясь на его ответе, я написал небольшой пример, который разъясняет (извините) и отвечает на мой оригинальный вопрос.

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

что приводит к следующему выводу

  #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

Мне все еще не нравится это. Как это работает, мне нужно провести тройную проверку всего, что делает код менее читабельным.

1

Другие решения

Вы пробежали через это с помощью отладчика?

Я догадываюсь, что у вас есть ошибка в вашем коде. полный и соответствующие части вашего кода помогут исключить вероятность того, что это ошибка Qt (на что, я готов поспорить, это не так).

Этот короткий тест ниже должен подтвердить, что QXmlStreamReader может анализировать пустой элемент:

const QString XML_STR = "<root><node /></root>";

int main(int /* argc */, char* /* argv[] */)
{

qDebug() << "Using readNextStartElement():";
{
QXmlStreamReader reader(XML_STR);

while(!reader.atEnd())
{
reader.readNextStartElement();
qDebug() << reader.name();
}
}

qDebug() << "Using readNext():";
{
QXmlStreamReader reader(XML_STR);

while(!reader.atEnd())
{
reader.readNext();
qDebug() << reader.name();
}
}

return 0;
}

Выход:

Using readNextStartElement():
"root""node""node""root"""Using readNext():
"""root""node""node""root"""
0

По вопросам рекламы [email protected]