1

Please help. I got a code that finds all folder, subfolders and files in given directory. And now I need to write them in XML document. Could it be possible without using parser? What should I add?

void PrintDir(char *parm)
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind;

    char buffer[MAX_PATH];
    char path[MAX_PATH];

    strcpy(path, parm);
    strcat(path, "*.*");

    hFind = FindFirstFile(path, &FindFileData);

    do
    {
        if (!strcmp(FindFileData.cFileName, ".") || !strcmp(FindFileData.cFileName, ".."))
            continue;

        if (FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
        {
            strcpy(buffer, parm);
            strcat(buffer, FindFileData.cFileName);
            printf("%s\n", buffer);
            strcat(buffer, "\\");
            PrintDir(buffer);
        }
        else
        {
            strcpy(buffer, parm);
            strcat(buffer, FindFileData.cFileName);
            printf("%s\n", buffer);
        }  
    }while(FindNextFile(hFind, &FindFileData));

    FindClose(hFind);
}
  • Is your goal to format and write the XML yourself, or are you open to using an XML library to just get the job done? Relevant SO question here: [what's the easiest way to generate xml in c++?](http://stackoverflow.com/questions/303371/whats-the-easiest-way-to-generate-xml-in-c) – NicholasM Jul 06 '14 at 17:54
  • I'm going to use a library, tinyXML for example. – Nevis Franko Jul 06 '14 at 18:29
  • You don't check for errors properly and you are simply begging for buffer overrun. And I cannot see any xml here. In fact I cannot really see a question at all. – David Heffernan Jul 06 '14 at 18:50

2 Answers2

0

I think the best way to approach this is "recursive descent" through the filesystem. Assuming that you want the XML hierarchy to match the filesystem hierarchy, I think you could define the following recursive function:

typedef boost::filesystem::path path;

void appendDirectoryToXML(const path& current_directory, XMLNode& current_node)
{
    for (subdirectory in directories(current_directory))
    {
       subirectory_xml_entry = new XML entry created in current_node;
       call appendDirectoryToXML(subdirectory, subirectory_xml_entry);
    }
    for (non_directory_file in files(current_directory))
    {
       add entry for non_directory_file to current_node;
    } 
}

The above is psuedocode; the exact details will depend on the details of the filesystem library and the XML library you use.

NicholasM
  • 4,557
  • 1
  • 20
  • 47
0

Try something like this:

#include <string>
#include <tinyxml.h> 

void PrintDir(const std::string &parm, TiXmlElement *parentElement)
{
    WIN32_FIND_DATA FindFileData;
    std::vector<std::string> subFolders, files;

    HANDLE hFind = FindFirstFileA((parm + "*.*").c_str(), &FindFileData);
    if (hFind == INVALID_HANDLE_VALUE)
        return;

    do
    {
        if (!strcmp(FindFileData.cFileName, ".") || !strcmp(FindFileData.cFileName, ".."))
            continue;

        if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            subFolders.push_back(FindFileData.cFileName);
        else
            files.push_back(FindFileData.cFileName);
    }
    while (FindNextFile(hFind, &FindFileData));

    FindClose(hFind);

    // optionally sort files...
    // optionally sort subFolders...

    for (std::vector<std::string>::iterator i = files.begin(), end = files.end(); i != end; ++i)
    {
        printf("%s%s\n", parm.c_str(), i->c_str());

        TiXmlElement *fileElement = new TiXmlElement("File");
        fileElement->SetAttribute("name", *i);
        parentElement->LinkEndChild(fileElement);
    }
    files.clear();

    for (std::vector<std::string>::iterator i = subFolders.begin(), end = subFolders.end(); i != end; ++i)
    {
        printf("%s%s\n", parm.c_str(), i->c_str());

        TiXmlElement *fileElement = new TiXmlElement("Folder");
        folderElement->SetAttribute("name", *i);
        parentElement->LinkEndChild(folderElement);

        PrintDir(param + *i + "\\", folderElement);
    }
}

TiXmlDocument doc;
TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "", "");
doc.LinkEndChild(decl);

TiXmlElement *filesystem = new TiXmlElement("FileSystem");
doc.LinkEndChild(filesystem);

TiXmlElement *driveElement = new TiXmlElement("Drive");
driveElement->SetAttribute("letter", "C");
filesystem->LinkEndChild(driveElement);

PrintDir("C:\\", driveElement);

doc.SaveFile("filesystem.xml");
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770