使用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个单独元素(开始/结束)的空元素?
修改 所以Huytard问我一个有效的例子。但他的回答引导我找到一个几乎回答了我的问题的解决方案。因此,我在答案中提出了一个明确的例子。
答案 0 :(得分:1)
感谢Huytard,我认识到这只是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 :(得分:0)
您是否使用调试器来完成此操作?
我的预感是您的代码中存在错误 - 因此发布完整以及代码的相关部分将有助于排除这是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"
""