Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating a XML file using Qt DOM

Tags:

dom

xml

qt

I have an application that builds a left menu that is based on a tree Qt component. In order to load it I need to parse a XML file. The XML file looks like:

<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>

I can actually read this XML using QtDOM.

    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,int>(     qdCmd,      rec    ));
                        descriptions.insert(pair<QString, Categories>( qdCmd, Desc) );
                    }
                    cat= cat.nextSibling();
                }
                model->setItem(r++,item);
            }
          }
          n = n.nextSibling();
    }

    file.close();

    return 0;

In between parsing I already assembly the menu. After all, I already have all set for updating the XML when the user edits the xml file and reloads at the application, I simply erase the tree and recreate it again. You can see that I also pass some data onto some structures, they are basically std::vector and std::map. This code above was written with examples from the Qt documentation, which are quite decent by the way.

It happens that I wrote a simple dialog to make the user avoiding editing the XML. Ok, for me it might be easier and simpler to edit the XML even from the user perspective, but the possible users will prefer to edit things on the dialog. This is all OK. I can grab the data pass it to the application. No trouble at all.

But I need to update the XML. Basically an edit will consist into updating the node by either adding a new one or inserting a child node into under . How do I update a node ? Is there any specific way to accomplish that ? My experiences with XML are short, I usually write, update, parse txt and binary files.

I want to do something like:

   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();
    }

It seems that using Qt Dom is quite decent for parsing and creating XML files, but it lacks the tools for updates. Any help would be much appreciated, even an example.

This other thread here, looks useful

Edit Value of a QDomElement?

I have looked over the internet for examples that would update a XML file. It seems that if I catch the current node I can add a child to it, so far I did not figure out how to do so.

Thanks for the help and obviously sorry for my ignorance.

like image 642
zlogdan Avatar asked Mar 21 '12 12:03

zlogdan


1 Answers

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);

This will result in:

<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>
like image 94
Chris Browet Avatar answered Sep 25 '22 15:09

Chris Browet