Search code examples
delphiexceptiondelphi-xe

Change behavior of TXMLDocument.SaveToFile


In production we sometimes have Exception of type "Access denied". The call stack is from this line

vXML.SaveToFile(Filename);

where vXML is IXMLDocument.

Problem here is that Filename is not logged. I tried this small testprogram.

implementation

uses
  xmldoc, Unit12;

{$R *.dfm}

procedure TForm11.FormShow(Sender: TObject);
const
  cnFile = 'C:\Program Files (x86)\test.xml';
var
  vXML: TAttracsXMLDoc;
begin
  vXML := TAttracsXMLDoc.Create(nil);
  try
    vXML.Active := True;
    // Process vXML
    vXML.SaveToFile(cnFile);
  finally
    vXML.Free;
  end;
end;

And other unit

unit Unit12;

interface

uses
  xmldoc,
  xml.xmldom,
  Xml.XMLIntf;

type
  TAttracsXMLDoc = class(TXMLDocument)
    procedure SaveToFile(const AFileName: DOMString); override;
  end;

implementation

uses
  Sysutils;

procedure TAttracsXMLDoc.SaveToFile(const AFileName: DOMString);
begin
  try
    inherited SaveToFile(AFileName);
  except
    on E: Exception do
    begin
      E.Message := E.Message + ' ' + AFileName + ' cannot be saved';
      raise;
    end;
  end;
end;

end.

It works as intended. But problem is that interface IXMLDocument is not used anymore. I want to use code like this:

procedure TForm11.FormShow(Sender: TObject);
const
  cnFile = 'C:\Program Files (x86)\test.xml';
var
  vXML: IXMLDocument;
begin
  vXML := NewXMLDocument;
  // Process vXML
  vXML.SaveToFile(cnFile);
end;

And with minimum changes on existing code catch exception above with a clear error of reason. What is the best path ?


Solution

  • Simply replace NewXMLDocument() with TAttracsXMLDoc, then you will get the behavior you want:

    function NewAttracsXMLDocument: IXMLDocument;
    begin
      Result := TAttracsXMLDoc.Create(nil);
    end;
    
    procedure TForm11.FormShow(Sender: TObject);
    const
      cnFile = 'C:\Program Files (x86)\test.xml';
    var
      vXML: IXMLDocument;
    begin
      vXML := NewAttracsXMLDocument; //NewXMLDocument;
      // Process vXML
      vXML.SaveToFile(cnFile);
    end;