Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Use QDirIterator to create an XML files
Forum Updated to NodeBB v4.3 + New Features

Use QDirIterator to create an XML files

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 1.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • CharlieGC Offline
    CharlieGC Offline
    CharlieG
    wrote on last edited by
    #1

    Hi,

    I want to create an xml file representing the contents of a folder. For example :

    Home
        |Test             //a file
        |Documents        //a folder
             |MyDoc1      //a file
        |Movies           //a folder
             |MyMovie1   //a file
        |Pictures         //a folder
             |MyPicture1 //a file
    

    will be represented by

    <root>
        <file>
            <name>Test</name>
        </file>
       <Documents>
           <file>
               <name>MyDoc1</name>
          </file>  
       </Documents>
       <Movies>
           <file>
               <name>MyMovie1</name>
          </file>  
       </Movies>
       <Pictures>
           <file>
               <name>MyPicture1</name>
          </file>  
       </Documents>
    </root>
    

    Obviously I don't know in advance the number of subfolders and files.

    Currently, here is my code :

    folder2Xml.h:

    #ifndef FOLDERMODEL_H
    #define FOLDERMODEL_H
    
    #include <QObject>
    #include <QDir>
    #include <QDirIterator>
    #include <QFile>
    #include <QDebug>
    #include <QXmlStreamWriter>
    
    class FolderModel : public QObject
    {
        Q_OBJECT
    
    
    public:
        explicit FolderModel(QObject *parent = 0);
    
    public slots:
        QStringList getXml(QString pathDir);
        void getContents(QString path);
    
    private:
        QString m_pathDir;
        QFile m_pathXmlFile;
        QXmlStreamWriter m_stream;
    
    };
    
    #endif // FOLDERMODEL_H
    

    folder2xml.cpp

    #include "foldermodel.h"
    
    FolderModel::FolderModel(QObject *parent) : QObject(parent)
    {
    
    }
    
    QStringList FolderModel::getXml(QString pathDir)
    {
        m_pathDir = pathDir;
    
    
        qDebug() << "Entre dans FolderModel::getContents(QString dirPath)";
        QDir dir(pathDir);
        dir.setSorting(QDir::Type);
        QStringList contentsFiles = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
    
        m_pathXmlFile.setFileName("path/to/myXml.xml");
        if (m_pathXmlFile.exists()) m_pathXmlFile.remove();
    
    
    
        if (m_pathXmlFile.open(QFile::Append)){
            m_stream.setDevice(&m_pathXmlFile);
            m_stream.setAutoFormatting(true);
            m_stream.writeStartDocument();
            m_stream.writeStartElement("root");
            m_stream.writeTextElement("version", "0.4");
    
    
            this->getContents(m_pathDir);
    
            m_stream.writeEndElement(); // <version>
            m_stream.writeEndDocument();
        }
    
        return contentsFiles;
    
    }
    
    void FolderModel::getContents(QString path)
    {
        QDirIterator iterator(path, QDir::Files | QDir::AllDirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
        while (iterator.hasNext()) {
            QFileInfo fileInfo = iterator.fileInfo();
    
            //qDebug() << fileInfo.absoluteFilePath() << fileInfo.absolutePath() << iterator.fileName();
    
            if(fileInfo.isFile()){
                m_stream.writeStartElement("file");
                m_stream.writeTextElement("name", fileInfo.fileName());
                m_stream.writeTextElement("size", QString::number(fileInfo.size()));
                m_stream.writeEndElement();
    
            }
            else{
                m_stream.writeStartElement(iterator.fileName());
                this->getContents(fileInfo.absoluteFilePath());
                m_stream.writeEndElement();
                //qDebug() << iterator.next();
            }
            iterator.next();
    
        }
    }
    

    But I have a problem with the result. My problem is with loops (while and if) in getContents. I can't correctly insert the files in the appropriate XML nodes.

    Can you help me ?

    Thank you for advance

    Charlie.

    1 Reply Last reply
    0
    • ? Offline
      ? Offline
      A Former User
      wrote on last edited by A Former User
      #2

      Hi! To read folder structures of arbitrary depth you need to use recursion. I made a small example but you need to add all the error checking.

      folderstuff.h

      #ifndef FOLDERSTUFF_H
      #define FOLDERSTUFF_H
      
      #include <QString>
      
      QString dirToXml(QString path);
      
      #endif // FOLDERSTUFF_H
      

      folderstuff.cpp

      #include "folderstuff.h"
      
      #include <QXmlStreamWriter>
      #include <QStringList>
      #include <QDir>
      
      void readDir(QString path, QXmlStreamWriter &sw)
      {
          const auto dirs = QDir(path).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
          for (const auto i : dirs) {
              sw.writeStartElement("directory");
              sw.writeAttribute("name", i);
              readDir(QDir(path+"/"+i).absolutePath(), sw);
              sw.writeEndElement();
          }
      
          const auto files = QDir(path).entryList(QDir::Files | QDir::NoDotAndDotDot);
          for (const auto i : files) {
              sw.writeStartElement("file");
              sw.writeAttribute("name", i);
              sw.writeEndElement();
          }
      }
      
      QString dirToXml(QString path)
      {
          QString result;
          {
              QXmlStreamWriter sw(&result);
              sw.setAutoFormatting(true);
              sw.writeStartDocument();
              sw.writeStartElement("rootdirectory");
              sw.writeAttribute("path", path);
              readDir(path, sw);
              sw.writeEndDocument();
          }
          return result;
      }
      

      main.cpp

      #include <QGuiApplication>
      #include <QFile>
      
      #include "folderstuff.h"
      
      int main(int argc, char *argv[])
      {
          QGuiApplication app(argc, argv);
          {
              const QString path("/home/charlie/downloads");
              QFile file("/home/charlie/dirlist.xml");
              file.open(QIODevice::WriteOnly);
              {
                  QTextStream ts(&file);
                  ts << dirToXml(path); // windows linebreaks: .replace("\n", "\r\n");
              }
          }
          return 0;
      }
      
      1 Reply Last reply
      5
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #3

        the only addition, replace const auto i with auto& i, it's (very marginally) faster

        P.S.
        constness of i is implied by constness of container

        EDIT:
        @Wieland is right, the gain is very limited, don't know why but this old article stuck in my head. but if you use the value version use const as it's not implied

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        ? 1 Reply Last reply
        2
        • VRoninV VRonin

          the only addition, replace const auto i with auto& i, it's (very marginally) faster

          P.S.
          constness of i is implied by constness of container

          EDIT:
          @Wieland is right, the gain is very limited, don't know why but this old article stuck in my head. but if you use the value version use const as it's not implied

          ? Offline
          ? Offline
          A Former User
          wrote on last edited by A Former User
          #4

          @VRonin Ah yes, you're right about the constness. But I'm not sure about the reference because QString is already implicitly shared. Anyways, good hint in general :-)

          1 Reply Last reply
          0
          • CharlieGC Offline
            CharlieGC Offline
            CharlieG
            wrote on last edited by
            #5

            It's super ...
            Thank you very much for your help.

            And the more I discover a new way to use the for loop (C ++ 11, I guess?).

            Thanks again.

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved