Using the File System Object (FSO) we can traverse through our website’s contents and write them out in a nicely nested form in an XML file. We could then use that file in a content management system or a TreeView control for example.
First we declare our variables:
<%@Language="VBScript"%> <%Option Explicit%> <%Response.Buffer = True%> <% '-- set a 600 second timeout value in case it hangs Server.ScriptTimeOut = 600 On Error Resume Next Dim strRootFolder Dim intLenRootFolder Dim objFSO Dim strXmlFile Dim strVbCrLf Dim strVbTab Dim numTree Dim objFile ...
Then we set them equal to some values:
... strVbCrLf = VbCrLf strVbTab = VbTab numTree = 0 strRootFolder = Request.ServerVariables("APPL_PHYSICAL_PATH") intLenRootFolder = Len(strRootFolder) strXmlFile = "<root type=""root"" value=""Site Root"" url=""/"">" & strVbCrLf ...
The strXmlFile is the root node of our XML file and we can set it equal to whatever we want as long as the type is equal to root.
Creating and writing to the XML file
... '-- create an instance of the FSO object Set objFSO = Server.CreateObject("Scripting.FileSystemObject") '-- open file for writing, create if not there, and open as text Set objFile = objFSO.CreateTextFile(strRootFolder & "menuitems.xml", True, False) '-- write root node objFile.Write(strXmlFile) ...
You can change the location of this file by adding folders in the Windows format. For example, to put it in a folder called navigation, change the location like so:
Set objFile = objFSO.CreateTextFile(strRootFolder & “navigation\menuitems.xml“, True, False)
Traversing through the site
... Call TraverseSite(strRootFolder,numTree) Sub TraverseSite(strFolder,thisTree) ...
We create a sub called TraverseSite, which is responsible for going through the folders of the site and creating nodes in our XML file. It accepts two parameters:
- strRootFolder : the specific folder we are in
- numTree: how many levels deep we are in the website folder structure
When we first call it, we pass the root folder to it, and 0 for the folder level. This sub gets called within itself as it goes deeper through the folders and the parameters change accordingly.
The basic logic for this sub is:
Take a folder Show name of folder without closing xml tag If there are subfolders Then For each subfolder Run same procedure with new folder and level Next End If If there are subfiles Then Show subfiles with closing xml tag End If Add closing xml tag
So, first we traverse through the folders:
... '-- reset the string which gets written to the XML file strXmlFile = "" '-- declare our variables in the sub Dim objFolder, objSubFolder, objSubFile, i Dim objThisFolder, objthisFile, strURL, strFolderURL '-- grab the folder passed in the sub Set objFolder = objFSO.GetFolder(strFolder) '-- grab its subfolders Set objSubFolder = objFolder.SubFolders '-- grab its files Set objSubFile = objFolder.Files '-- properly nest the nodes for a nice display For i = 1 To thisTree strXmlFile = strXmlFile & strVbTab Next '-- get the folder path excluding the application root folder strFolderURL = Mid(objFolder.Path, intLenRootFolder, Len(objFolder.Path)) '-- turn the physical path into a relative path strFolderURL = Replace(strFolderURL, "\", "/") '-- append node to the output unless it is the root folder If thisTree > 0 Then strXmlFile = strXmlFile & "<folder type=""folder"" value=""" & objFolder.Name & """ url=""" & strFolderURL & "/"">" & strVbCrLf objFile.Write(strXmlFile) End If '-- reset the string output again strXmlFile = "" '-- if there are subfolders under it then run sub again for each one If Not IsEmpty(objSubFolder) Then For Each objThisFolder in objSubFolder Call TraverseSite(objThisFolder.Path,thisTree + 1) Next End If ...
Then we loop through the file contents of each folder we are in:
... '-- if there are files in the folder If Not IsEmpty(objSubFile) Then For Each objthisFile in objSubFile '-- properly nest the nodes for a nice display For i = 0 To thisTree + 1 strXmlFile = strXmlFile & strVbTab Next '-- get the virtual path strURL = Mid(objthisFile.Path, intLenRootFolder, Len(objthisFile.Path)) strURL = Replace(strURL, "\", "/") '-- create output string strXmlFile = strXmlFile & "<document type=""document"" value=""" & objthisFile.Name & """ url=""" & strURL & """/>" & strVbCrLf Next '-- write output to XML file objFile.Write(strXmlFile) strXmlFile = "" End If For i = 1 To thisTree strXmlFile = strXmlFile & strVbTab Next '-- close the folder node If thisTree > 0 Then strXmlFile = strXmlFile & "</folder>" & strVbCrLf End If objFile.Write(strXmlFile) strXmlFile = "" '-- show the progress of the code as it goes through folders Response.Write("Folder <font color=""#FF0000"">" & strFolderURL & "</font> written!<br>") Response.Flush End Sub '--write end root node objFile.Write("</root>") objFile.close Set objFile = Nothing Set objFSO = Nothing %>
XML file created
The resulting XML file, menuitems.xml, should look something like this:
Including other properties in the XML file
The name and path of a folder/file may be the basic output here, but we can easily expand them to include other properties as well. For example, using FSO we can also output the size, date created, date last modified, etc. To add for example the date last modified of files to the XML file output, change the strXmlFile output above (in the file output section) like so:
... strXmlFile = strXmlFile & "<document type=""document"" value=""" & objthisFile.Name & """ url=""" & strURL & """" & " datelastmodified=""" & objthisFile.DateLastModified & """/>" & strVbCrLf ...
And the expanded XML file output would then look like this:
We can of course go beyond the FSO object for outputing properties in the XML file. We could for example, instantiate a component that reads image properties if the file we are on happens to be an image, and include those properties as well in the output – like image width, height etc.