我有一个应用程序,它构建一个基于树Qt组件的左菜单.为了加载它我需要解析
XML文件.
XML文件如下所示:
<comandos> <categoria> <nome>Cupom fiscal</nome> <comando> <nome>01 - Abrir Cupom Fiscal</nome> <env>3</env> <rec>4</rec> <desc>CNPJ / CPF : </desc> <desc>Nome : </desc> <desc>Endereco: </desc> </comando> </categoria> </comandos>
我实际上可以使用QtDOM读取这个XML.
QDomDocument doc( "ComandosML" ); QFile file( "comandos.xml" ); int r = 0; datafields.clear(); receFields.clear(); categories.clear(); if( !file.open( QIODevice::ReadOnly ) ) return -1; if( !doc.setContent( &file ) ) { file.close(); return -2; } // Ok we are ready to parse DOM QDomElement root = doc.documentElement(); if( root.tagName() != "comandos" ) return -3; QDomNode n = root.firstChild(); while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if( e.tagName() == "categoria" ) { QDomNode cat = n.firstChild(); while( !cat.isNull() ) { QDomElement CatName = cat.toElement(); if ( CatName.tagName() == "nome") { QString s = CatName.text(); if ( s != "") { categories.push_back(s); item = new QStandardItem( (s) ); item->setEditable(false); } } if ( CatName.tagName() == "comando") { QDomNode params = cat.firstChild(); QString qdCmd; int env = 0; int rec = 0; Categories Desc; while ( !params.isNull()) { QDomElement ParamName = params.toElement(); if ( ParamName.tagName() == "nome") { qdCmd = ParamName.text(); child = new QStandardItem( (qdCmd) ); child->setEditable( false ); child->setDragEnabled(false); item->appendRow( child ); } else if ( ParamName.tagName() == "env") { env = ParamName.text().toInt(); } else if ( ParamName.tagName() == "rec") { rec = ParamName.text().toInt(); } else if ( ParamName.tagName() == "desc") { Desc.push_back(ParamName.text()); } params = params.nextSibling(); } datafields.insert(pair<QString,int>( qdCmd,env )); receFields.insert(pair<QString,rec )); descriptions.insert(pair<QString,Categories>( qdCmd,Desc) ); } cat= cat.nextSibling(); } model->setItem(r++,item); } } n = n.nextSibling(); } file.close(); return 0;
在解析之间我已经组装了菜单.毕竟,当用户编辑xml文件并在应用程序重新加载时,我已经准备好更新XML,我只需擦除树并再次重新创建它.你可以看到我也将一些数据传递给一些结构,它们基本上是std :: vector和std :: map.上面的代码是用Qt文档中的示例编写的,顺便说一句,这些代码相当不错.
碰巧我写了一个简单的对话框,让用户避免编辑XML.好吧,对我来说,即使从用户的角度来看,编辑XML也可能更容易和简单,但可能的用户更愿意在对话框上编辑内容.这一切都好.我可以抓取数据传递给应用程序.没问题.
但我需要更新XML.基本上,编辑将包括通过添加新节点或在子节点下插入子节点来更新节点.如何更新节点?有没有具体的方法来实现这一目标?我对XML的经验很简短,我经常编写,更新,解析txt和二进制文件.
我想做的事情如下:
if( root.tagName() != "comandos" ) return -3; QDomNode n = root.firstChild(); while( !n.isNull() ) { QDomElement e = n.toElement(); if( !e.isNull() ) { if( e.tagName() == "categoria" ) { QDomNode cat = n.firstChild(); while( !cat.isNull() ) { QDomElement CatName = cat.toElement(); if ( CatName.tagName() == "nome") { QString s = CatName.text(); if ( s != qsCategory ) { // we have not found the category // add it here } else { // the category exists simply update } } cat= cat.nextSibling(); } } } n = n.nextSibling(); }
似乎使用Qt Dom非常适合解析和创建XML文件,但它缺少更新工具.任何帮助都会非常感激,甚至是一个例子.
这里的另一个帖子看起来很有用
我查看了互联网上有关更新XML文件的示例.看来,如果我抓住当前节点,我可以添加一个孩子,到目前为止我还没弄清楚如何这样做.
谢谢你的帮助,显然很抱歉我的无知.
解决方法
QDomElement newCategoriaTag = doc.createElement(QString("categoria")); QDomElement newNoMetag = doc.createElement(QString("nome")); QDomText newNomeText = doc.createTextNode(QString("Cupom fiscal 2")); newNoMetag.appendChild(newNomeText); newCategoriaTag.appendChild(newNoMetag); root.appendChild(newCategoriaTag);
这将导致:
<comandos> <categoria> <nome>Cupom fiscal</nome> <comando> <nome>01 - Abrir Cupom Fiscal</nome> <env>3</env> <rec>4</rec> <desc>CNPJ / CPF : </desc> <desc>Nome : </desc> <desc>Endereco: </desc> </comando> </categoria> <categoria> <nome>Cupom fiscal 2</nome> </categoria> </comandos>