Forum > Documentation (Maintaining -)
FPDoc Editor in Lazarus changes XML files as soon as it opens it
avra:
--- Quote from: Martin_fr on July 22, 2021, 03:10:40 pm ---Or did I misread the OT?
It sounded to me like the build in editor
--- End quote ---
You're right. Bug is in the built in Lazarus FPDoc Editor.
--- Quote from: Martin_fr on July 22, 2021, 03:10:40 pm ---For a start point: ide/fpdoceditwindow.pas
--- End quote ---
Tried a quick look but got lost pretty soon, so beyond my reach. Reported as https://bugs.freepascal.org/view.php?id=39282.
Can anyone confirm this bug on Linux Lazarus trunk?
avra:
I have just opened original "ISO-8859-1" encoding sysutils.xml with external LAZDE (Lazarus Documentation Editor) built from trunk, added short description to TByteHelper.ToBinString and saved XML. It was the same bug. Newly saved sysutils.xml had "UTF-8" encoding and many line endings added. The same as with simpler Lazarus built in FPDoc Editor described initially.
avra:
Just checked the Debian x64 with trunk and the bug is the same there, too.
avra:
It looks like LAZDE is using WriteXMLFile() from xmlwrite to write content of TXMLDocument to file. According to https://wiki.lazarus.freepascal.org/xmlwrite, the only supported encoding is UTF8, '>' is converted to '>' because of forced character escaping, indent is forced and LineEndings are OS specific (TDOMWriter can help with indent and lineendings).
Before, and even after calling WriteXMLFile(FDocument, FN), encoding is still ISO-8859-1, so it is clear that WriteXMLFile() is to blame for creating a XML diff nightmare. Is there some alternative to WriteXMLFile() without using 3rd party XML lib?
avra:
Ok, here is a quick hack to fix FPC XML files after edited with FPDocEditor or LazDE, using simple replacement transformation pairs. XML will not be formatted like the original, but close enough for diff patch trial if patch applyer skips obvious. Tested only on sysutils.xml. Feel free to improve.
--- Code: Pascal [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //// fixfpcxml utility to fix FPC XML files after edited with FPDocEditor or LazDE, by Zeljko Avramovic (c) 2021 //// //// When FPDocEditor or LazDE are used for editing FPC XML documentation files (like sysutils.xml from RTL), //// encoding and formating of saved XML files are changed so much that creating a diff patch file is pointless. //// This utility tries to fix that. Although not perfect, result XML is much closer to the original format. //// Tested only on sysutils.xml. Feel free to improve it further. //// //// Dual license: //// 1. FPC modified LGPL (chosen for compatibility with FreePascal and Lazarus) //// 2. BSD3 (chosen for compatibility with everything else) //// //// Usage: //// fixfpcxml <xmlfilename> //// //// Examples: //// fixfpcxml sysutils.xml //// fixfpcxml c:\Prg\Lazarus\fpdoctrunk\sysutils.xml //// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// program fixfpcxml; {$mode objfpc} {$H+} uses classes, sysutils, strutils, dom, xmlwrite, xmlread; procedure ShowHelpAndExit;begin WriteLn(''); WriteLn('Usage:'); WriteLn(' fixfpcxml <xmlfilename>'); WriteLn(''); WriteLn('Examples:'); WriteLn(' fixfpcxml sysutils.xml'); WriteLn(' fixfpcxml c:\Prg\Lazarus\fpdoctrunk\sysutils.xml'); WriteLn(''); Halt;end; const CRLF: string = #13 + #10; Blanks64 = ' '; Blanks14 = ' '; Blanks10 = ' '; Blanks4 = ' ';var i: integer; XmlFileName: string; S: TFileStream; W: TDOMWriter; XmlDoc: TXMLDocument; StrList: TStringList;begin try try WriteLn('fixfpcxml utility to fix FPC XML files after edited with FPDocEditor or LazDE, by Zeljko Avramovic (c) 2021'); if ParamCount() <> 1 then ShowHelpAndExit; XmlFileName := ParamStr(1); if not FileExists(XmlFileName) then begin WriteLn('ERROR: File ', XmlFileName, ' does not exist'); Exit; end; if UpperCase(ExtractFileExt(Trim(XmlFileName))) <> '.XML' then begin WriteLn('ERROR: File ', XmlFileName, ' must have XML extension'); Exit; end; ReadXMLFile(XmlDoc, XmlFileName); S := TFileStream.Create(XmlFileName, fmCreate); W := TDOMWriter.Create(S, XmlDoc); W.UseTab := false; W.IndentSize := 0; W.WriteNode(XmlDoc); W.Free; S.Free; StrList := TStringList.Create; StrList.LoadFromFile(XmlFileName); StrList.Text := StringReplace(StrList.Text, 'encoding="utf-8"', 'encoding="ISO-8859-1"', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<descr>This documentation', '<descr>' + CRLF + 'This documentation', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '>', '>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<p>', '<p>' + CRLF, [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<td>', '<td>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '</th>', '</th>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '</tr>', '</tr>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '</td>', '</td>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '</dd>', '</dd>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<dd>', '<dd>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<dd>' + CRLF + '<var>', '<dd><var>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<tr><td>' + CRLF, '<tr><td>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, Blanks14 + CRLF, '', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, Blanks10 + CRLF, '', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, Blanks64, '', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, Blanks4, '', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<li>' + CRLF + '<link', '<li><link', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<var>PChar', '<var>PChar', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<var>TDateTime', '<var>TDateTime', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<var>DateTime', '<var>DateTime', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<var>ShortDate', '<var>ShortDate', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<var>LongTime', '<var>LongTime', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<printshort', '<printshort', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<errors>', '<errors>' + CRLF, [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + ' <var', ' <var', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + ' ' + CRLF + ' ', '', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + ' <var>', CRLF + '<var>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, ' ' + CRLF + '<var>', ' <var>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, ' ' + CRLF + ' <link', ' <link', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, ' ' + CRLF + '<link', ' <link', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '/' + CRLF + '<link', '/<link', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<seealso/>', '<seealso>' + CRLF + '</seealso>', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, CRLF + '<file>C:', ' <file>C:', [rfReplaceAll, rfIgnoreCase]); StrList.Text := StringReplace(StrList.Text, '<remark>', '<remark>' + CRLF, [rfReplaceAll, rfIgnoreCase]); StrList.SaveToFile(XmlFileName); StrList.Free; WriteLn('Finished fixing file ', XmlFileName); except on e: Exception do WriteLn(e.Message); end; finally ; end;end.
If you do not change any old info, and just add new stuff which did not exist in original XML, then after saving XML from FPDocEditor all new stuff is at the end of the document, as shown in the screenshot. It may be optimal to just copy/paste and report these changes to FPC XML doc maintanier, instead of complicating with fixfpcxml.
Navigation
[0] Message Index
[*] Previous page