无法使用QXMLStreamReader识别空元素

Cannot identify empty Elements with QXmlStreamReader

本文关键字:识别 元素 QXMLStreamReader      更新时间:2023-10-16

我使用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;
  }
  [...]
}

文档说:

空的元素也被报道为开头,然后直接进行endlement。

我可以使用ReadNext(),但仍未收到最终元素。看来解析器只能检测到

<tag></tag>

作为空元素,但不是

<tag/>

那么,是我还是QT中存在问题?如果是这样,我如何检测不包括2个分离元素(start/end)的空元素?

编辑:因此,惠塔德(Huytard)问我一个工作的例子。但是他的回答使我找到了一个几乎回答我的问题的解决方案。因此,我在答案中提出了一个澄清的例子。

因此,感谢Huytard,我认识到这只是QXMLStreamReader :: ReadNextStartEllement的行为,这是出乎意料的。我期望的是,它实际上只会读 start 元素。最初,我想事先检查一个元素是否为空,然后决定如何处理其内容。似乎这是不可能的。我引用了自己的文档所涵盖的可能性。IE。即使原子元素是空的,它实际上是启动元素,该元素实际上是最终元素。那很糟糕,因为您不能回到流中。

根据他的回答,我写了一个小例子,既澄清(抱歉)并回答了我的最初问题。

  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

我仍然不喜欢它。我需要进行三次检查的所有工作方式,使代码不那么可读。

您是否正在使用调试器进行此操作?

我的直觉是您的代码中有一个错误 - 因此,发布完整和代码的相关部分将有助于排除这是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" 
""