我在使用Qt QXmlStreamReader (QT4.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(),但仍然没有接收到end元素。似乎解析器只能检测到
<tag></tag>作为一个空元素,但不是
<tag/>那么,是我的问题还是Qt中存在的问题?如果是这样的话,如何检测不包含两个独立元素(开始/结束)的空元素?
编辑:所以Huytard问我一个有用的例子。但他的回答让我找到了一个几乎回答了我问题的解决方案。因此,我在答覆中举出一个明确的例子。
发布于 2014-01-23 08:59:42
因此,多亏了Huytard,我才意识到这只是QXmlStreamReader::readNextStartElement的行为,这在某种程度上是出乎意料的。我所期望的是,它实际上只会读取start元素。最初,我想事先检查元素是否为空,然后决定如何处理其内容。看来这是不可能的。而我引用的文件也涵盖了这种不可能的情况。也就是说,即使一个原子元素是空的,它实际上是一个开始元素,它实际上是一个结束元素。这很糟糕,因为你不能回到小溪里去。
基于他的回答,我写了一个小例子,既澄清了(对不起),又回答了我最初的问题。
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我还是不喜欢。按照我的工作方式,我需要对每件事情进行三次检查,这会降低代码的可读性。
发布于 2014-01-22 18:28:05
你用调试器运行过这个过程吗?
我的直觉是,您的代码中有一个bug -所以发布完整的和代码的相关部分将有助于排除这是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"
"" https://stackoverflow.com/questions/21280705
复制相似问题