Macro Command XMLFormatDocument

Macro Command XMLFormatDocument

6

    Oct 06, 2020#1

    Hello,

    Using UltraEdit v27.10.0.108.
    I have searched this forum, read release notes for 27.x on the UltraEdit website, and Googled for this command with no results. Don't know if it is a new command or not but I just noticed it today.
    What does the macro command XMLFormatDocument do? There are no parameters associated with it in the Edit/Create Macro window and when I add it to a new macro  (tried a path to a file and a folder) and try to save the macro, a popup window states "Incorrect Macro Command" for XMLFormatDocument.
    I was wondering if this command would be the equivalent of Reformat XML in the Coding menu.

    Thank you for any help.

    6,686585
    Grand MasterGrand Master
    6,686585

      Oct 07, 2020#2

      The Edit/Create Macro dialog window contains at bottom of Command  list the two undocumented commands XMLCompressDocument and XMLFormatDocument in addition to documented command XMLConvertToCRLF.

      The two undocumented commands are not (yet) supported by UltraEdit macro editor/creator/recorder. I think, there is the plan to support these two commands in a future version, but they are not (yet) supported by UltraEdit for Windows v27.10.0.108.

      The existing documented and working command XMLConvertToCRLF is the same as Reformat XML in submenu XML of contemporary menu Coding respectively traditional menu Format.

      I found out further that an execution of command Reformat XML during macro recording does result in neither XMLConvertToCRLF nor XMLFormatDocument being in the recorded macro using UltraEdit for Windows v27.00.0.24 (second public released v27.00) to v27.10.0.108 (currently latest version). The execution of command XML convert to CR/LFs in UltraEdit v26.20.0.68 and former versions during recording of a macro results in having macro command XMLConvertToCRLF in recorded macro. XMLConvertToCRLF is also recorded with UltraEdit for Windows v27.00.0.22 (first public released v27.00 replaced two days later already by build 24). UE v27.00.0.22 has only XMLConvertToCRLF in Command  list while v27.00.0.24 has additionally also XMLCompressDocument and XMLFormatDocument in the list.

      Conclusion: It looks like there is the plan to make the commands Compress XML and Reformat XML available also as macro commands XMLCompressDocument and XMLFormatDocument, but the implementation is not finished yet and UltraEdit users have to add macro command XMLConvertToCRLF to a macro to get the behavior of command Reformat XML during macro execution.
      Best regards from an UC/UE/UES for Windows user from Austria

      6

        Oct 07, 2020#3

        Thank you so much, Mofi, for the thorough explanation and history on this. Since XMLConvertToCRLF performs as Reformat XML in a macro, I will try that command for reformatting folders with subfolders of XML files.

        Thank you again for your help! You have always been a wealth of knowledge on this forum which I've been visiting since the mid-2000s.

        6,686585
        Grand MasterGrand Master
        6,686585

          Nov 06, 2020#4

          The macro commands  XMLCompressDocument and XMLFormatDocument are fully implemented in UltraEdit for Windows v27.10.0.148 and UEStudio v20.10.0.52 as also the UltraEdit document scripting commands xmlCompressDocument and xmlFormatDocument.
          Best regards from an UC/UE/UES for Windows user from Austria

          6

            Nov 06, 2020#5

            Excellent! Thank you for the information! :)

              Jun 15, 2021#6

              Back to this particular task after months on another task. :) Is there a way to run XMLFormatDocument in a macro across thousands of files in a folder of subfolders (without opening the files in UE)? It's not a standard find/replace in files for particular text so... what I need to do is simple, just need to run it across thousands of files in a folder of subfolders...
              UE version 28.10.0.26

              InsertMode
              ColumnModeOff
              HexOff
              XMLFormatDocument
              Find RegExp "^t"
              Replace All ""

              As a work-around, I'm currently using PlayMacro with the above macro on a files list from the folder but got a UE "out of memory" error after going through three file lists of around 1,000 files each.

              6,686585
              Grand MasterGrand Master
              6,686585

                Jun 15, 2021#7

                The only commands running on files without opening them in UltraEdit are Find in Files and Replace in Files. It is of course possible to use a macro or a script which first gets a list of full qualified file names of all files in a folder or a folder tree to process using Find in Files and then opens one filter after the other for running the XML reformatting command, saving and closing the reformatted file.

                I suggest to look on GetListOfFiles for a script solution more or less ready to use on looking on the demo example.

                Code: Select all

                // === GetListOfFiles ========================================================
                
                /* Script Name:   GetListOfFiles
                   Creation Date: 2008-04-16
                   Last Modified: 2018-11-14
                   Copyright:     Copyright (c) 2018 by Mofi
                   Original:      https://www.ultraedit.com/resources/scripts/GetListOfFiles.js
                                  http://forums.ultraedit.com/viewtopic.php?f=52&t=5442
                
                The function   GetListOfFiles   creates in an edit window a list of files
                according to the arguments passed to the function. It uses the command
                Find in Files   with advanced option   Results to edit window   for
                creating the file list.
                
                The return value of the function is   true   if a file list could be created
                with at least one file name, otherwise   false   is returned by the function.
                
                The new file with the file list is the active file and the caret is at top
                of the file on success finding at least one file matching the criteria.
                
                The function requires UltraEdit for Windows >= v13.10 or UEStudio >= v6.30.
                
                Unicode file names are supported by UltraEdit for Windows >= v24.00 and
                UEStudio >= v17.00. For former versions don't use this function on file names
                containing a character not included in system code page for non-Unicode aware
                applications and set value of variable   bNoUnicode   in the function below
                to value   true   to get ANSI encoded file names.
                
                The function expects 1 number, 2 strings and 1 boolean as input parameters:
                
                  1) nFileList - is the number which specifies the kind of file list
                                 to be created by the function.
                
                     The possible values are:
                
                        0 ... get list of files in a specified directory.
                        1 ... get list of open files.
                        2 ... get list of favorite files.
                        3 ... get list of project files.
                        4 ... get list of solution files (only supported by UEStudio).
                
                     Value 0 is used by default if this parameter is not specified
                     at all, or is not of type number, or contains a wrong number.
                
                     The other three function parameters are evaluated only if 0 is used
                     for the first function parameter and should be omitted on using 1-4.
                
                  2) sDirectory - is the initial directory for the search.
                
                     The current working directory ".\" is used by the function if this
                     string is empty and a search in a directory is set by first parameter.
                
                     This parameter is ignored for all other file list types.
                
                     The working directory is by default the directory active on start
                     of UltraEdit/UEStudio. In the properties of a shortcut the working
                     directory can be specified in the edit field named "Start in".
                
                  3) sFileType - contains the file type specification like "*.txt" or
                     "ga*.htm;et*.htm".
                
                     This string is only used for the search in a specified directory.
                
                     "*" is used by the function if this parameter is not correct specified.
                
                  4) bSubDirs - is a boolean parameter which determines to find files only
                     in the specified directory with value false, or also in subdirectories
                     with value true.
                
                     This boolean is only used for the search in a specified directory.
                
                     The default value is false if the parameter is not correct specified.
                
                NOTE:
                
                An existing edit window from a previous Find in Files run is not closed
                and therefore the results of the search for the file names are appended
                to the existing content of the file. This makes it possible to run this
                function multiple times with different values for the parameters to get
                one large file list.
                
                ATTENTION:
                
                The first two strings in the function code below must be adapted to used
                version of UE/UES if a localized version of UltraEdit or UEStudio is used
                because otherwise the function does not work as designed. And the function
                uses also a non-regular expression search and sets all find parameters as
                needed for this search.
                
                A debug message is shown by the function on an error condition if a global
                variable named   g_nDebugMessage   exists and has the value 1 for debugging
                to output window or 2 for debugging with message boxes. No debug messages
                are displayed if there is no global variable with name g_nDebugMessage with
                a valid value.
                
                This function is copyright protected by Mofi for free usage by UE/UES
                users. The author cannot be made responsible for any damage caused by
                this function. You use it at your own risk.
                
                HINT:
                
                The list can be loaded into an array of file names with following code:
                
                UltraEdit.activeDocument.selectAll();
                var asFileNames = UltraEdit.activeDocument.selection.split("\r\n");
                // Last element of array is usually an empty string because all file
                // names in the list are terminated usually with a DOS line termination.
                // This empty string is removed from the array. The number of file names
                // is then equal the number of array elements (length property).
                if (asFileNames[asFileNames.length-1] == "") asFileNames.pop();
                // The results file with the list of file names is no longer needed
                // when using now the file names in the array asFileNames.
                UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
                
                The main script can use next a for loop to open a found file, modify
                the opened file, save and close it, and continue with next file until
                all files have been modified. Extra code is needed to make the already
                opened file active instead of opening it if it is possible that some of
                the files in the list are already opened. For details see on forum topic
                http://forums.ultraedit.com/viewtopic.php?f=52&t=4596#p26710 the hint on
                common mistake "Opening a file already open from within script does not
                result in reloading file content and making the file active". */
                
                
                function GetListOfFiles (nFileList, sDirectory, sFileType, bSubDirs)
                {
                   /* The summary info line at bottom of a Find in Files result depends
                      on application language as also the name of the results file.
                      Please adapt the following two strings to your version of UE/UES.
                
                      Please click on ribbon tab "Advanced" or in menu "Advanced" on
                      "Settings" or "Configuration", expand tree item "Search" and select
                      item "Find output format" or "Set Find Output Format". The displayed
                      configuration dialog contains the "Find summary" definition at bottom
                      with the format string to assign below to variable sSummaryInfo.
                
                      Even better is executing once the command "Find in Files" with an
                      empty search string with advanced (gearwheel) option "Results to
                      edit window" checked. The "Find in Files" floating window or docked
                      view can be opened by
                
                      a) pressing default hotkey Ctrl+Shift+F;
                      b) clicking on ribbon tab "Home" in second group "Search" on
                         last item "Find/replace in files" on using ribbon mode;
                      c) clicking in menu "Home" on the menu item "Find/replace in files"
                         on using toolbar/menu mode with contemporary menus;
                      d) clicking in menu "Search" on menu item "Find/replace in files"
                         respectively "Find in Files" on using toolbar/menu mode with
                         traditional menus or UE 
                < v23.00 respectively UES < v16.00.
                
                      After running "Find in Files" with an empty search string listing
                      with results written to an edit window with at least one file name
                      in results window , look on file tab of results window and last
                      line in results file and adapt the two strings below accordingly.
                
                      It is also possible to just open GetListOfFiles.js and execute it with
                      Alt+Shift+R to see how the find results look like in used version of
                      UE/UES on having entered the parameters correct during script execution.
                
                      Please note that variable sSummaryInfo must be initialized with
                      an empty string on having disabled the "Find summary" completely. */
                
                   var sSummaryInfo = "Search complete. Found";
                   var sResultsDocTitle = "** Find Results ** ";  // Note the space at end!
                
                   // The default strings for German UltraEdit are:
                   // var sSummaryInfo = "Suche abgeschlossen, ";
                   // var sResultsDocTitle = "** Suchergebnisse ** ";
                
                   /* Modify the value of this variable to true on using UltraEdit
                      for Windows < v24.00 or UEStudio < v17.00 which do not support
                      correct loading Unicode strings from Unicode files into memory. */
                   var bNoUnicode = false;
                
                
                   /* Determine the type of output for debug messages from the global
                      variable g_nDebugMessage: 1 ... debug to output window, 2 ... debug
                      to message dialog, all others ... no debug messages. A debug message
                      is displayed with a popup message box like on using the value 2 if
                      a global number variable g_nDebugMessage does not exist at all. */
                   var nOutputType = (typeof(g_nDebugMessage) == "number") ? g_nDebugMessage : 2;
                   if ((nOutputType < 1) || (nOutputType > 2)) nOutputType = 0;
                
                   if (typeof(nFileList) != "number" || nFileList 
                    < 0 || nFileList > 4) nFileList = 0;
                
                   if (!nFileList)      // Search in a specified directory?
                   {
                      // Use current working directory if no directory is specified.
                      if ((typeof(sDirectory) != "string") || (!sDirectory.length)) sDirectory = ".\\";
                      // Append a backslash if it is missing at end of the directory string.
                      else if (sDirectory[sDirectory.length-1] != "\\") sDirectory += "\\";
                      // Search for all files if no file type is specified.
                      if ((typeof(sFileType) != "string") || (!sFileType.length)) sFileType = "*";
                      if (typeof(bSubDirs) != "boolean") bSubDirs = false;
                   }
                   else
                   {
                      sDirectory = "";    // For the list of open, favorite, project
                      sFileType = "";     // or solution files the other 3 parameters
                      bSubDirs = false;   // have always the same default values.
                   }
                
                   // Remember current regular expression engine.
                   var nRegexEngine = UltraEdit.regexMode;
                   /* A regular expression engine must be defined or the find
                      for the last line in the Unicode results could fail. */
                   UltraEdit.ueReOn();
                
                   /* Run a Find in Files with an empty search string to get the
                      list of files stored in the specified directory in an edit
                      window and delete the last line with the summary info. */
                   UltraEdit.frInFiles.directoryStart=sDirectory;
                   UltraEdit.frInFiles.filesToSearch=nFileList;
                   UltraEdit.frInFiles.matchCase=false;
                   UltraEdit.frInFiles.matchWord=false;
                   UltraEdit.frInFiles.regExp=false;
                   UltraEdit.frInFiles.searchInFilesTypes=sFileType;
                   UltraEdit.frInFiles.searchSubs=bSubDirs;
                   UltraEdit.frInFiles.unicodeSearch=false;
                   UltraEdit.frInFiles.useOutputWindow=false;
                   if (typeof(UltraEdit.frInFiles.openMatchingFiles) == "boolean")
                   {
                      UltraEdit.frInFiles.openMatchingFiles=false;
                   }
                   UltraEdit.frInFiles.find("");
                
                   /* The results of the search above are appended if the Find in Files
                      results window was already opened before running Find in Files. But
                      the results file does not get automatically the focus as it does if
                      there was no results file open from a previous search. Therefore care
                      must be taken that the file with the Find in Files results is the
                      active document after the search to continue on correct file. */
                   var bListCreated = false;
                   if (UltraEdit.activeDocument.path == sResultsDocTitle) bListCreated = true;
                   else
                   {
                      for (var nDocIndex = 0; nDocIndex 
                        < UltraEdit.document.length; nDocIndex++)
                      {
                         if (UltraEdit.document[nDocIndex].path == sResultsDocTitle)
                         {
                            UltraEdit.document[nDocIndex].setActive();
                            bListCreated = true;
                            break;
                         }
                      }
                   }
                   if (bListCreated && sSummaryInfo.length)
                   {
                      // Search for the summary info at bottom of the results.
                      UltraEdit.activeDocument.findReplace.searchDown=false;
                      UltraEdit.activeDocument.findReplace.matchCase=true;
                      UltraEdit.activeDocument.findReplace.matchWord=false;
                      UltraEdit.activeDocument.findReplace.regExp=false;
                      UltraEdit.activeDocument.findReplace.find(sSummaryInfo);
                      bListCreated = UltraEdit.activeDocument.isFound();
                   }
                   UltraEdit.activeDocument.findReplace.searchDown=true;
                   switch (nRegexEngine)     // Restore original regular expression engine.
                   {
                      case 1:  UltraEdit.unixReOn(); break;
                      case 2:  UltraEdit.perlReOn(); break;
                      default: UltraEdit.ueReOn();   break;
                   }
                   /* Check next if the Find above was successful on finding last line in
                      the active document which should contain the Find in Files results. */
                   if (!bListCreated)
                   {
                      if (nOutputType == 2)
                      {
                         UltraEdit.messageBox('There is a problem with command frInFiles or the strings of the two script variables "sSummaryInfo" and "sResultsDocTitle" are not adapted to used version of UltraEdit/UEStudio!',"GetListOfFiles Error");
                      }
                      else if (nOutputType == 1)
                      {
                         if (!UltraEdit.outputWindow.visible) UltraEdit.outputWindow.showWindow(true);
                         UltraEdit.outputWindow.write('GetListOfFiles: There is a problem with command frInFiles or the strings of the two script variables');
                         UltraEdit.outputWindow.write('                "sSummaryInfo" and "sResultsDocTitle" are not adapted to used version of UltraEdit/UEStudio!');
                      }
                      return false;
                   }
                
                   // Delete last line in results file if line with summary info was found.
                   if (sSummaryInfo.length) UltraEdit.activeDocument.deleteLine();
                   UltraEdit.activeDocument.top();
                
                   /* Next convert the file into an ASCII/ANSI file for better handling of
                      the file names by UltraEdit for Windows < v24.00 and UEStudio < v17.00.
                      Unicode file names are not supported by these versions of UE/UES. There
                      is no need for this conversion if the file with the results is already
                      an ASCII file from a previous execution of function GetListOfFiles. */
                   if (bNoUnicode)
                   {
                      UltraEdit.activeDocument.key("RIGHT ARROW");
                      if (UltraEdit.activeDocument.currentPos > 1) UltraEdit.activeDocument.unicodeToASCII();
                      else UltraEdit.activeDocument.top();
                   }
                
                   // No files were found if top of file is also end of file.
                   if (UltraEdit.activeDocument.isEof())
                   {
                      if (nOutputType > 0)
                      {
                         var sMessage;
                         switch (nFileList)
                         {
                            case 0:  sMessage = "No file " + sFileType + " was found in directory" +
                                                ((nOutputType == 2) ? "\n\n" : " ") + sDirectory; break;
                            case 1:  sMessage = "There are no opened files."; break;
                            case 2:  sMessage = "There are no favorite files."; break;
                            case 3:  sMessage = "There are no project files or no project is opened."; break;
                            case 4:  sMessage = "There are no solution files or no solution is opened."; break;
                            default: sMessage = ""; break;
                         }
                         if (nOutputType == 1)
                         {
                            if (!UltraEdit.outputWindow.visible) UltraEdit.outputWindow.showWindow(true);
                            UltraEdit.outputWindow.write("GetListOfFiles: "+sMessage);
                         }
                         else UltraEdit.messageBox(sMessage,"GetListOfFiles Error");
                      }
                      UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
                      return false;
                   }
                   return true;
                }  // End of function GetListOfFiles
                
                
                if (GetListOfFiles(0,"C:\\Path\\Folder\\","*.xml",true))
                {
                   // If there was no error and files are found in the directory, the
                   // function made the search results output with the file names active.
                   // Select all lines in the file and load the file names into an array.
                   UltraEdit.activeDocument.selectAll();
                   var sLineTerm = "\r\n";   // Default line terminator type is DOS.
                   var nLineTermPos = UltraEdit.activeDocument.selection.search(/\r\n|\n|\r/);
                   if (nLineTermPos >= 0)    // Any line terminator found?
                   {
                      // The list file is a Unix file if first character found is a line-feed.
                      if (UltraEdit.activeDocument.selection[nLineTermPos] == '\n') sLineTerm = "\n";
                      // The list file is a Mac file if first character found is a carriage
                      // return and the next character is not a line-feed as in a DOS file.
                      else if (UltraEdit.activeDocument.selection[nLineTermPos+1] != '\n') sLineTerm = "\r";
                   }
                   var asFileNames = UltraEdit.activeDocument.selection.split(sLineTerm);
                
                   // The list is not needed anymore and therefore the results window is closed.
                   UltraEdit.closeFile(UltraEdit.activeDocument.path,2);
                   asFileNames.pop();  // Remove empty string at end of the list.
                   
                   // Now open one file after the other, process it, save and close the file.   
                   // No file in the list should be opened already on script start! Why?
                   // http://forums.ultraedit.com/viewtopic.php?f=52&t=4596#p26710
                   // contains the answer on point 7 and the solution to enhance
                   // this script further if this is necessary in some cases.
                   for (var nFileIndex = 0; nFileIndex < asFileNames.length; nFileIndex++)
                   {
                      UltraEdit.open(asFileNames[nFileIndex]);
                
                      UltraEdit.activeDocument.xmlFormatDocument();
                
                      // Save and close the processed file.
                      UltraEdit.closeFile(UltraEdit.activeDocument.path,1);
                   }
                }
                
                The script worked on my test with UE v28.10.0.26 on a folder with 46 XML files with the exception of the last file. For some unknown reasons the last XML file in folder is opened by UltraEdit, but the XML reformatting and the file save is not done on last XML file. That is a very strange issue which I have to report to IDM support by email.

                A macro solution would be also possible according to Run Macro on all files within folder in theory with following macro code:

                Code: Select all

                InsertMode
                ColumnModeOff
                HexOff
                FindInFiles "C:\Path\Folder\\" "*.xml" ""
                Loop 0
                Find MatchCase Up "Search complete. Found"
                IfFound
                ExitLoop
                Else
                NextWindow
                EndIf
                EndLoop
                DeleteLine
                Top
                Loop 0
                IfEof
                ExitLoop
                EndIf
                StartSelect
                Key END
                IfSel
                Open "^s"
                XMLFormatDocument
                CloseFile Save
                EndIf
                EndSelect
                DeleteLine
                EndLoop
                CloseFile NoSave
                
                But the macro solution does not work because of UltraEdit for Windows v28.10.0.26 runs into a deadlock after having processed already some XML files and showing the Cancel window although macro property Show cancel dialog for this macro is not checked because of the macro took already more than two seconds for execution. This extra cancel feature was introduced with UltraEdit for Windows v26.20.

                It helps to disable syntax highlighting, code folding and the XML parser in configuration before running the macro for even faster processing the XML files, but than UltraEdit crashes after having processed 25 files on my test. It looks like the macro solution is a bit too fast processed by UltraEdit.

                I have to report the issue found with the script and the macro solution by email to IDM support.

                I noticed also that the default summary string of a Find in Files changed in the meantime. So the very long time standard "Search complete, found" as used in script function GetListOfFiles by default and in the macro code in referenced topic must be now "Search complete. Found" with UltraEdit for Windows v28.10.
                Best regards from an UC/UE/UES for Windows user from Austria

                6

                  Jun 15, 2021#8

                  Thank you, Mofi! I will look into these solutions and appreciate your research on them. Interesting that there are issues also that you're reporting to IDM support. I don't recall having out of memory errors so early in a process in earlier versions of UE. 
                  For now, I'm probably going to continue with the list of files and the macro because I have a due date (Friday) for doing a bunch of code changes to these XML files after I reformat them.

                    Jun 16, 2021#9

                    Also getting UE crashing which is unusual. Got a bug report if that is of any use.

                    6,686585
                    Grand MasterGrand Master
                    6,686585

                      Jun 16, 2021#10

                      Thanks, but I have bug reports and crash dump files too. So I can create full packages on weekend for easy reproducing all the issues by IDM support and the UltraEdit developers for getting them fixed soon. Easy to reproduce crashes are usually fixed very fast as a crash of an application is always of highest priority for bug fixing.
                      Best regards from an UC/UE/UES for Windows user from Austria