0

Im try develop a helper to read/write and control an instance of TXMLDocument. I write a simple unit for this work. The unit have a procedure that assign the instance to global variable, and set some variables for document control. The unit is:

unit Globals;

{ Variables globales de la aplicacion, con sus correspondientes accessors }

interface

uses
  { XML Helper }
  xmldom, XMLIntf, msxmldom, XMLDoc, SysUtils, DateUtils;

type
  XmlCheckPoint = Record
    asociado: boolean;
    xmlFile: TXMLDocument;
    saved: boolean;
    lastModification: TDateTime;
    lastSave: TDateTime;
    path: TFilename;
  End;

  { Firmas }
  procedure assignXml(var aXml: TXMLDocument);
  procedure xmlWriteProyectoNode(obra,cliente,ubicacion,fecha,sondeo,estudio: String);
  function existsXml(): boolean;
  function xmlIsUpdated(): boolean;

var
  Xml: XmlCheckPoint;

The procedure assignXml, works fine:

  procedure assignXml(var aXml: TXMLDocument);
  begin
    Xml.xmlFile := aXml;
    Xml.asociado := true;
    Xml.saved := false;
    Xml.lastSave := Yesterday;
    Xml.path := '';
    { Inserto el nodo raiz }
    Xml.xmlFile.Active := true;
    Xml.xmlFile.AddChild('raiz');
    Xml.lastModification := Now();
  end;

But, xmlWriteProyectoNode(...) explodes the app:

procedure xmlWriteProyectoNode(obra,cliente,ubicacion,fecha,sondeo,estudio: String);
  var
    root,meta,child: IXMLNode;
  begin
    Xml.xmlFile.Active := true;
    root := Xml.xmlFile.DocumentElement;
    meta := root.AddChild('proyecto');
    child := meta.AddChild('obra');
    child.Text := obra;
      [...]
    Xml.lastModification := Now();
  end;

The app crash when invoques writeXmlProyectoNode(...) with an Access Violation Error. In execution time. The Embarcadero debuger says that the conflicting line is:

root := Xml.xmlFile.DocumentElement;

I need get the root element, and was think this was the correct way... Im newest in Delphi, any ideas ?. Thanks !.

Edit: The XML Creation ( newXml type is TXMLDocument )

newXml := TXMLDocument.Create(nil);
newXml.Options := [doNodeAutoIndent];
newXml.Active := true;
{ Asocio la instancia de XMLDocument a mi variable global newXml}
Globals.assignXml(newXml);
Arioch 'The
  • 15,799
  • 35
  • 62
ramiromd
  • 2,019
  • 8
  • 33
  • 62
  • There is no `Xml` in parameters of `procedure xmlWriteProyectoNode`. So - where does it take it from ? and what is the value of `XML` at the start of procedure. Add the 1st line of `procedure xmlWriteProyectoNode` as `ShowMessage(IntToStr(Integer(Pointer(XML))));` – Arioch 'The Jul 13 '13 at 22:23
  • Also show the code creating `TXMLDocument` ! this class has a number of traps and how you create it is one of those! BTW, "with an Access Violation Error" is better than nothing, but is less than what Delphi told you. Please copy the exact error message here. – Arioch 'The Jul 13 '13 at 22:25
  • `root := Xml.xmlFile.DocumentElement;` is complex line. And "complex" is the same as "ambiguous". Split it to simpler lines. `tempvar := Xml.xmlfile; root := tempvar.DocumentElement;` – Arioch 'The Jul 13 '13 at 22:27
  • @AriochThe "XML" is a record inside the unit. In XML.xmlFile is the instance of TXMLDocument associated in assignXml(). – ramiromd Jul 13 '13 at 22:28
  • what is the declaration of newXML there ? what is the data type of the var ? – Arioch 'The Jul 13 '13 at 22:31
  • newXml type is TXMLDocument. – ramiromd Jul 13 '13 at 22:33
  • I do your suggest in the 3th comment: `tempvar := Xml.xmlfile; root := tempvar.DocumentElement;` the app fails in `tempvar := Xml.xmlFile` – ramiromd Jul 13 '13 at 22:35
  • That means you don't have any valid object referenced in XML variable. Either the object does no more exist or the variable has no pointer to that object. I asked you for copying exact error text and `ShowMessage`'ing the value of `XML` variable, but you did not do it and no one has the information to help you. – Arioch 'The Jul 13 '13 at 22:38

1 Answers1

3
   var newXml: TXMLDocument; // instead of "iXMLDocument"
   newXml := TXMLDocument.Create(nil);

And now please read the documentation about creating the document with or without the owner.

You should either create it as plain object, that lives until you .Free it - but then it should have an owner.

Or you should use reference-counted interfaces and ALWAYS keep at least one variable alive that links to the document.

The latter approach shown in... again in the documentaton:

Read the documentation

PS.

Community
  • 1
  • 1
Arioch 'The
  • 15,799
  • 35
  • 62
  • or you could make `newXml` type `iXMLDocument` instead as documentation shows, and other variables too. That is a very traps-rich class, so if you want to use it - you have to read the manuals, really have to. – Arioch 'The Jul 13 '13 at 22:42