将 QXmlStreamReader 实例传递给类
Posted
技术标签:
【中文标题】将 QXmlStreamReader 实例传递给类【英文标题】:Pass QXmlStreamReader Instance to Class 【发布时间】:2014-07-16 23:19:34 【问题描述】:我正在尝试使用 QXmlStreamReader 读取 XML 文档。当我尝试将指向读者的指针传递给其他类时,我遇到了问题。我在一个类中创建了一个阅读器实例。该类读取 XML,直到遇到定义新类的块。我创建了新类的实例,然后调用该类中的一个函数来继续读取特定于它的 XML。例如:
void SF_UnitClass::ReadModes()
Q_ASSERT(XML.isStartElement() && XML.name() == MODES);
NumModes = XML.attributes().value(COUNT).toInt();
while (XML.readNextStartElement())
if (XML.name() == MODE)
ModeClass* pMode = new ModeClass(this);
ModeList += XML.attributes().value(ID).toString();
pMode->ReadXML(&XML);
else
XML.raiseError(QObject::tr("Something other than Mode block encountered in Modes block"));
void ModeClass::ReadXML(QXmlStreamReader* pXML)
Q_ASSERT(pXML->isStartElement() && pXML->name() == MODE);
while (pXML->readNextStartElement())
int nameIndex = ModeList.indexOf(pXML->name().toString());
if(nameIndex != -1)
switch(nameIndex)
case 0:
qDebug() << "Mode: Receivers";
NumReceivers = pXML->readElementText().toInt();
break;
case 1:
qDebug() << "Mode: Channels";
ReadChannels(pXML);
break;
case 2:
qDebug() << "Mode: Servos";
ReadServos(pXML);
break;
else
qDebug() << "Mode: Error " << name;
pXML->raiseError(QObject::tr("Unrecognized keyword for Mode"));
void ModeClass::ReadChannels(QXmlStreamReader* pXML)
Q_ASSERT(pXML->isStartElement() && pXML->name() == CHANNELS);
NumChannels = pXML->attributes().value(COUNT).toInt();
while (pXML->readNextStartElement())
if (pXML->name() == CHANNEL)
qDebug() << "Mode: Read Channel";
ChannelClass* pChannel = new ChannelClass(this);
pChannel->ReadXML(pXML);
else
pXML->raiseError(QObject::tr("Something other than Channel block enc
void ModeClass::ReadServos(QXmlStreamReader* pXML)
Q_ASSERT(pXML->isStartElement() && pXML->name() == SERVOS);
NumServos = pXML->attributes().value(COUNT).toInt();
while (pXML->readNextStartElement())
if (pXML->name() == SERVO)
qDebug() << "Mode: Read Servo";
ServoClass* pServo = new ServoClass(this);
pServo->ReadXML(pXML);
else
qDebug() << "Servos: raiseError";
pXML->raiseError(QObject::tr("Something other than Servo block encou
qDebug() << "Mode: Read Servos Exit";
void ChannelClass::ReadXML(QXmlStreamReader* pXML)
Q_ASSERT(pXML->isStartElement() && pXML->name() == CHANNEL);
ChannelNumber = pXML->attributes().value(ID).toInt();
while (pXML->readNextStartElement())
int nameIndex = ChannelList.indexOf(pXML->name().toString());
if(nameIndex != -1)
switch(nameIndex)
case 0:
UserName = pXML->readElementText();
break;
case 1:
EndPointHold = String2Bool(pXML->readElementText());
break;
case 2:
ServoPriority = String2Bool(pXML->readElementText());
break;
else
pXML->raiseError(QObject::tr("Unrecognized keyword for Channel"));
void ServoClass::ReadXML(QXmlStreamReader* pXML)
Q_ASSERT(pXML->isStartElement() && pXML->name() == SERVO);
ServoNumber = pXML->attributes().value(ID).toInt();
while (pXML->readNextStartElement())
int nameIndex = ServoList.indexOf(pXML->name().toString());
qDebug() << "Servo: NameIndex: " << nameIndex;
if(nameIndex != -1)
switch(nameIndex)
case 0:
Offset = pXML->readElementText().toInt();
break;
case 1:
PosFactor = pXML->readElementText().toInt();
break;
case 2:
NegFactor = pXML->readElementText().toInt();
break;
case 3:
SecServo = pXML->readElementText().toInt();
break;
case 4:
Unit = pXML->readElementText().toInt();
break;
case 5:
Ser1 = pXML->readElementText().toInt();
break;
case 6:
Ser2 = pXML->readElementText().toInt();
break;
case 7:
Ser3 = pXML->readElementText().toInt();
break;
else
qDebug() << "Servo: raiseError";
pXML->raiseError(QObject::tr("Unrecognized keyword for Servo block")
qDebug() << "Servo: Exit ";
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<SmartFlyUnit version="1.0">
<UnitName>PowerExpander Eq10E</UnitName>
<UnitCode>PE-5</UnitCode>
<UnitID>1</UnitID>
<MinRev>1.0</MinRev>
<MaxRev>1.9</MaxRev>
<Servos>36</Servos>
<Outputs>32</Outputs>
<UnitMode>Chan</UnitMode>
<Modes Count="2">
<Mode ID="Chan">
<Receivers>1</Receivers>
<Channels Count="10">
<Channel ID="0">
<UserName></UserName>
<EndPtHold>Off</EndPtHold>
<ServoPri>Off</ServoPri>
</Channel>
<Channel ID="1">
<UserName></UserName>
<EndPtHold>Off</EndPtHold>
<ServoPri>Off</ServoPri>
</Channel>
</Channels>
<Servos Count="36">
<Servo ID="0">
<Offset>0</Offset>
<PosFact>1.0000</PosFact>
<NegFact>1.0000</NegFact>
<Reverse>Off</Reverse>
<SecServo>0xFF</SecServo>
<Unit>0xFF</Unit>
<Ser1>0xFF</Ser1>
<Ser2>0xFF</Ser2>
<Ser3>0xFF</Ser3>
</Servo>
<Servo ID="1">
<Offset>0</Offset>
<PosFact>1.0000</PosFact>
<NegFact>1.0000</NegFact>
<Reverse>Off</Reverse>
<SecServo>0xFF</SecServo>
<Unit>0xFF</Unit>
<Ser1>0xFF</Ser1>
<Ser2>0xFF</Ser2>
<Ser3>0xFF</Ser3>
</Servo>
</Servos>
</Mode>
</Modes>
<MCUs Count="1">
<MCU ID="0">
<FileName>/PE-5/PE-5_M0_1_00.sffw</FileName>
</MCU>
</MCUs>
<FPGAs Count="1">
<FPGA ID="0">
<Configs Count="2">
<Config ID="0">
<FileName>/PE-5/PE-5_F0C0_1_00.sffw</FileName>
</Config>
<Config ID="1">
<FileName>/PE-5/PE-5_F0C1_1_00.sffw</FileName>
</Config>
</Configs>
</FPGA>
</FPGAs>
</SmartFlyUnit>
我添加了 ModeClass 用来识别通道和伺服模块的代码。我还添加了 ChannelClass 和 ServoClass 的代码。最后,我添加了我的 XML 文件的编辑版本,但足以显示问题。这个 XML 可以很好地读入我的 TreeWidget 代码(未显示)。当我将它读入上面的代码时发生的情况是所有通道都被正确读取,然后它读取第一个伺服块并一直返回到主 ModeClass 循环,而不是读取 ModeClass::ReadServos 中的下一个伺服。我知道这是很多代码,但它似乎是显示问题的唯一方法。谢谢,
【问题讨论】:
你需要发布 pMode->ReadXML 的正文 好的,在我正在阅读的代码和 XML 中添加了更多内容。 【参考方案1】:Qt 文档说:
读取直到当前元素中的下一个开始元素。退货 当到达起始元素时为真。当结束元素是 达到,或者发生错误时,返回false。
所以当你遇到起始元素时,使用readNextStartElement()
会在你找到的元素内部搜索
即
<xml>
</xml>
<xml>
</xml>
这里会发生什么:
readNextStartElement()
将在第一个 <xml>
节点上停止
readNextStartElement()
将返回 false,因为它发现 </xml>
在稍微修改的例子中:
<xml>
<child>
</child>
</xml>
<xml>
</xml>
readNextStartElement()
将在第一个 <xml>
节点上停止
readNextStartElement()
将在 <child>
节点上停止
readNextStartElement()
将返回 false,因为 <child>
节点内没有 xml 节点
请问你应该怎么做?
在您到达您感兴趣的节点并阅读您需要的所有信息后,您必须调用skipCurrentElement()
,以便QXmlStreamReader
将转到当前元素的末尾
所以稍微修改一下第一个示例:
<xml>
</xml>
<xml>
</xml>
readNextStartElement()
将在第一个 <xml>
节点上停止
skipCurrentElement()
将在第一个 <xml>
节点关闭时停止
readNextStartElement()
将在第二个 <xml>
节点停止
【讨论】:
我明白你在说什么,但我正在阅读整个文件并且应该识别所有节点。没有什么我想跳过的。我正在从 XML 构建一个数据库。我发布了更多代码和一个简短的 XML 文件。我希望添加对有效和无效的更好的描述。谢谢。 当然,您不想跳过任何内容。您是否尝试使用调试器来查看您的解析代码到底在哪里停止?在SF_UnitClass::ReadModes()
中设置断点并逐步进行
由于某种原因,我在调试器上遇到了问题。我设置了一个断点,当我到达那里时,如果我跳过它会给我一个错误,说它不能插入断点 -422 并停止调试。调试器必须配置错误,但我不知道如何修复它。如果我只是运行程序没有错误,它只是没有按照我的意愿去做。这就是我使用调试语句的原因。
好吧,我觉得自己很笨。这一切正常,但在我的开关中,我错过了一个案例,所以阅读变得不按顺序。我需要 switch 中的默认值来警告我该块有一个不在 switch 语句中的元素,然后调用 skipCurrentElement()。感谢您的帮助,您的示例确实帮助我意识到我所缺少的。
很高兴我可以指导您找到解决方案,而不是在盘子上给出它:)以上是关于将 QXmlStreamReader 实例传递给类的主要内容,如果未能解决你的问题,请参考以下文章