Handling the Files

This topic discusses the code that handles the following tasks for the PT application:

The code for the Lingo.Build method accepts as arguments the name of a source directory containing the XML template files, a destination directory to hold the results of the build process, and a string variable containing the name of the lingo.xml file that is the source of text strings for the new HTML pages. The following code fragment shows the function prototype for Lingo.Build:

Public Sub Build(ByVal sSourcePath As String, ByVal sDestination As String, ByVal lingo As String)

The code initializes the sFiles variable for use in the call to the GetFiles subroutine, which retrieves each file with an .xml extension. The two If. . .Then decision structures verify that the source and destination path strings end in backslashes (\); if they do not, the code appends a backslash. With the values of variables sSourcePath, sDestination, and sFiles properly initialized, the code calls GetFiles. The following code fragment illustrates this process:

  Dim sFiles As String
  On Error GoTo Errhandler
  'set the appropriate initializing values
  sFiles = "*.xml"
  
  If Not Right(sSourcePath, 1) = "\" Then
      sSourcePath = sSourcePath & "\"
  End If
  If Not sDestination = "" Then
    If Not Right(sDestination, 1) = "\" Then
       sDestination = sDestination & "\"
    End If
       Call GetFiles(sSourcePath, sDestination, sFiles)

GetFiles Subroutine

The GetFiles subroutine uses the custom data types declared in the LingoDeclaration.bas module. The code iterates through each globalized XML template file, passes it into the Translate function to be populated with values from lingo.xml, and then stores the results as an .htm file in the destination directory. The following code illustrates the GetFiles subroutine:

Public Sub GetFiles(ByVal sSourcePath As String, _
                         ByVal sDestination As String, _
                          ByVal sFiles As String, _
                          ByVal LingoFileName As String)

   Dim WFD As WIN32_FIND_DATA
   
   Dim r As Long
   Dim hFile As Long
   Dim bNext As Long
   Dim copied As Long
   Dim currFile As String
   Dim fileNumber As Long
   Dim fileName As String
   
   On Error GoTo Errhandler

The first statements in the following code retrieve a search handle from the call to FindFirstFile. The FindNextFile and FindClose functions use this search handle in subsequent blocks of code. The search handle points to the first XML file in the path that is stored in the variable sSourcePath, the PT application's Global directory. The WIN32_FIND_DATA structure holds data about the file that FindFirstFile finds. Subsequent code can access this data.

  'Start searching for files in the source directory.
   hFile = FindFirstFile(sSourcePath & sFiles, WFD)
   
   If (hFile = INVALID_HANDLE_VALUE) Then
      'nothing to do
       err.Raise err.number, err.source, err.description
       '"No " & sFiles & " files found."
       Exit Sub
   
   End If

Next, the code isolates the file name into the currFile variable by using the Left$ and InStr functions. This is necessary because the file name accessed in WFD.cFileName (populated after the return from FindFirstFile) has a maximum length of 260 characters, which is set by the MAX_PATH constant declared in LingoDeclaration.bas. The calls to Left$ and InStr remove the buffer of nulls that occupies the difference between the length of the file name and the value of MAX_LENGTH.

If the call to FindFirstFile returns a valid search handle, the code executes a Do. . .Loop statement, as follows:

  'get each file to the new directory with *.htm extension
   If hFile Then
        Do
         currFile = Left$(WFD.cFileName, InStr(WFD.cFileName, Chr$(0)) - 1)

The next block of code starts the process of building a localized HTML file with a call to the Translate function. The object variable ASP references the ASP Response object and communicates the progress of the build process to the browser.

To build the HTML files that populate the destination directory, the code uses the Visual Basic FreeFile function to obtain a file number that is not already in use. Next, the code names the file with a fully resolved path and an .htm extension. The If Not. . .Else block checks to see if the just-named .htm file already exists in the application's file system; if it is not found, ASP.Write indicates that the code is building the file, which begins with the call to Translate. If the call to Translate returns with a result other than NULL, the code writes the resulting HTML into the file.

The following code fragment illustrates this process:

         'give any number in range of 1 - 255 
         fileNumber = FreeFile
         'change the extension from .xml to .htm
         fileName = sDestination & Left$(currFile, InStrRev(currFile, ".", -1, vbTextCompare)) & "htm"
If Not FileExists(fileName) Then
           If Not ASP Is Nothing Then
            ASP.Write "Building " & currFile & "...<BR>"
           End If
            'resultString is the merged *.htm file
            resultString = Translate(sSourcePath & currFile, sDestination & sLingo)
            If Not (resultString = "" Or IsEmpty(resultString)) Then
               Open fileName For Output Lock Read Write As #fileNumber
               Print #fileNumber, resultString
               Close #fileNumber
            End If
         Else
           If Not ASP Is Nothing Then
            ASP.Write currFile & " already built. Skipping...<BR>"
           End If
         End If

The next code fragment gets the search handle of the next file in the sSourcePath variable, the application's Global directory. The code returns to the top of the Do…Loop statement until the FindNextFile function returns zero, indicating that the loop has processed all of the XML template files. The code then exits the loop and calls FindClose to close the search handle.

        'find the next file matching the initial file spec
         bNext = FindNextFile(hFile, WFD)
       Loop Until bNext = 0
   End If
     
ASP.Write "Done..."
   'Close the search handle
   Call FindClose(hFile)
   Exit Sub