我必须实现一个xml解析器,它在运行时构建和放置一个小部件中的Qt对象。我写了一个基于this的解析器。模块代表将保留QWidget
和QPushButton
实例的QCheckBox
。 xml
是QXmlStreamReader
,就像Qt参考中的示例一样。
所以,在这里我尝试解析这个非常基本的xml文件:
<somexml version="1.0">
<module>
<button label="Send UART" define="BUTTON0" pos="30, 30" size="20, 10">
<action cmd="sendCom" data="0xAA 0xBB 0xCC"/>
</button>
<checkbox label="Send UART" define="CHECKBOX0" pos="250, 30" size="20, 10">
<action cmd="sendCom" data="test"/>
</checkbox>
<button label="Check BIT" define="BUTTON1" pos="140, 30" size="20, 10">
<action cmd="setDef" data="BUTTON0=1"/>
</button>
</module>
</somexml>
模块元素将创建一个小部件来保存标签内的复选框和按钮。所以这里:
void XmlReader::readXml()
{
while (xml.readNextStartElement())
{
if (xml.name() == "module")
{
readModule();
}
}
}
我希望读取模块元素并输入readModule
的范围。在readModule
内部,我真的很难跟踪解析流程。
以下是实施:
void XmlReader::readModule()
{
Q_ASSERT(xml.isStartElement() && xml.name() == "module");
while (xml.readNextStartElement())
{
if (xml.name() == "button")
{
readButton(widget);
}
else if (xml.name() == "checkbox")
{
readCheckBox(widget);
}
else
{
xml.skipCurrentElement();
}
}
}
它只会到达xml文件中的第一个button
元素并创建一个按钮。发送UART。
当我将readXml
的实施更改为:
void XmlReader::readXml()
{
while (xml.readNextStartElement())
{
if (xml.name() == "module")
{
readModule();
}
else if (xml.name() == "button")
{
readButton(widget);
}
else if (xml.name() == "checkbox")
{
readCheckBox(widget);
}
else
{
xml.skipCurrentElement();
}
}
}
它将到达第一个按钮和第一个复选框。我错过了什么?
编辑:添加了readButton的实现
void XmlReader::readButton(Widget *widget)
{
Q_ASSERT(xml.isStartElement() && xml.name() == "button");
QString label = xml.attributes().value("label").toString();
QString define = xml.attributes().value("define").toString();
QString pos = xml.attributes().value("pos").toString();
QStringList posList = pos.split(",");
int posX = posList[0].toInt();
int posY = posList[1].toInt();
QString size = xml.attributes().value("size").toString();
QStringList sizeList= size.split(",");
int sizeX = sizeList[0].toInt();
int sizeY = sizeList[1].toInt();
QString cmd, data;
while (xml.readNextStartElement())
{
if (xml.name() == "action")
{
cmd = xml.attributes().value("cmd").toString();
data = xml.attributes().value("data").toString();
}
else
{
xml.skipCurrentElement();
}
}
if (cmd == "sendCom")
{
widget->createButton(label, define, posX, posY,
SLOT(sendCom(QString)), data);
}
else if (cmd == "setDef")
{
widget->createButton(label, define, posX, posY,
SLOT(setDef(QString)), data);
}
}
答案 0 :(得分:0)
您需要在xml.skipCurrentElement();
和readButton(widget);
之后使用readCheckBox(widget);
。没有xml.readNextStartElement()
读取元素的结尾并打破循环。
void XmlReader::readModule()
{
Q_ASSERT(xml.isStartElement() && xml.name() == "module");
while (xml.readNextStartElement())
{
if (xml.name() == "button")
{
readButton(widget);
xml.skipCurrentElement();
}
else if (xml.name() == "checkbox")
{
readCheckBox(widget);
xml.skipCurrentElement();
}
else
{
xml.skipCurrentElement();
}
}
}