A little research (and testing clearly confirms<g>) that using
TXMLDocument.Create(nil) in code isn't safe. So, I took comments from some
of the searching I did and ended up using a model that looks something like:
procedure MyProc(XMLData: string);
var
XMLDoc: IXMLDocument;
ThisNode: IXMLNode;
begin
XMLDoc:=LoadXMLData(XMLData);
XMLDoc.Active
ThisNode:=XMLDoc.DocumentElement.ParentNode; // creates node equiv to
.Node on TXMLDocument;
MyRecursiveProcToDoStuff(ThisNode); // proc designed to accept
TXMLDocument.Node
end;
OK, so this works and doesn't crash. No apparent memory leaks, etc, etc.
At least it works on my machine. My problem is that I don't understand what
it's doing and how it's doing it. That bothers me a lot, for software that
will be distributed to others' machines.
Example of things I do not know (OK, that is a very long list<g>):
Where's the beef? That is: With TXMLDocument I know what parser it's
using, so on distribution I can make sure it's there. What is IXMLDocument
doing for a parser?
Were does it live and die? I presume it's working as a normal variable
and cleanup occurs when it goes out of scope, but I sorta need to actually
*know*.
What is the functionality difference vs TXMLDocument. That is, it
crashes if I try XMLDoc.Node so that must not be implemented. What other
issues will there be, and how would I know that?
Is the above process safe to do on a routine basis? What are the "gotcha's"
and limitations? What is the "solid and preferred" methodology for handling
XML in Delphi, without a form or data module? If there isn't a clear
answer to that, can someone give me a clue on the best direction? My "plan
B" is to create a data module on the fly, put the TXMLDocument on that, then
kill the DM when done but that sounds real ugly.
Be gentle, I'm an old VB guy<g>
Thanks,
Dan
It's using the default one.
To change it, add the following units to your uses clause:
- xmldom
- oxmldom
Now, in your initialization section write this:
DefaultDomStr := 'OpenXML';
That's it. You changed the default dom parser to OpenXML.
> Were does it live and die? I presume it's working as a normal variable
> and cleanup occurs when it goes out of scope, but I sorta need to actually
> *know*.
> What is the functionality difference vs TXMLDocument. That is, it
> crashes if I try XMLDoc.Node so that must not be implemented. What other
> issues will there be, and how would I know that?
Why does it crash? It shouldn't, as long as you're accessing an existing
node.
> Is the above process safe to do on a routine basis? What are the "gotcha's"
> and limitations? What is the "solid and preferred" methodology for handling
> XML in Delphi, without a form or data module? If there isn't a clear
> answer to that, can someone give me a clue on the best direction? My "plan
> B" is to create a data module on the fly, put the TXMLDocument on that, then
> kill the DM when done but that sounds real ugly.
And it is.
Taken from my XML editor:
private
FDocument : IXMLDocument;
...
procedure MyForm.OnCreate( Sender : TObject );
begin
FDocument := TXMLDocument.Create( nil ) as IXMLDocument;
end;
> Be gentle, I'm an old VB guy<g>
Ok, for this time we'll be :D
> Thanks,
HTH,
> Dan
Andrew
P.S. There are a few things I don't understand in your code, such as
this:
ThisNode:=XMLDoc.DocumentElement.ParentNode;
// creates node equiv to .Node on TXMLDocument;
This will create the document-root node, i.e., not the root node.
To make it clearer, say you have this document:
<rootnode>
<childnode/>
</rootnode>
That code will return the #document node *before* the root node.
If you want to return the root node, you need DocumentElement.
Also, you got to activate the XML document like this:
XMLDoc.Active := True;
HTH again :D
--
You can subscribe my blog at
http://www.andrearaimondi.net/rss.php or
http://www.andrearaimondi.net/atom.php
Dan Barclay wrote:
> Were does it live and die? I presume it's working as a normal variable
> and cleanup occurs when it goes out of scope, but I sorta need to actually
> *know*.
interfaces are reference-counted (see delphi docs about interfaces). the
object instances that they refer to are destroyed when the variable goes
out of scope and their reference counter is 0.
> What is the functionality difference vs TXMLDocument.
there is no functionality difference. IXMLDocument is implemented by a
TXMLDocument. look at the source code of LoadXMLData: it actually
creates a TXMLDocument but just returns an interface. so, methods and
properties are in fact the same.
> What other
> issues will there be, and how would I know that?
search the newsgroups. i remember some quirks with NodeCollection (that
happens with TXMLDocument as well, though).
> Is the above process safe to do on a routine basis?
absolutely.
> What is the "solid and preferred" methodology for handling
> XML in Delphi, without a form or data module?
IXMLDocument.
> Be gentle, I'm an old VB guy<g>
you may want to learn about the difference between interfaces and objects.
--matthias
> I need some help understanding IXMLDocument (in particular) and
> parallels with TXMLDocument. I've used TXMLDocument for a bit
> with some success, though I don't claim to be an XML expert. The
> situation is that I want to use (something like) TXMLDocument, but
> have created at runtime without a container.
IXMLDocument is an interface. TXMLDocument is a component (and the
implementation class of IXMLDocument). TXMLDocument derives from
IXMLDocument, so they have the same functionality. To instantiate an
instance of IXMLDocument, use the LoadXML...() or NewXML...()
functions.
> A little research (and testing clearly confirms<g>) that using
> TXMLDocument.Create(nil) in code isn't safe.
Yes, it is. That is exactly what the VCL does internally when using
IXMLDocument. The real issue is in how you are using
TXMLDocument.Create(nil) in the first place. If you assign it to a
TXMLDocument variable, then that is bad. You have to assign it to an
IXMLDocument variable so that it is treated as an interface properly.
> procedure MyProc(XMLData: string);
You should pass the string as 'const':
procedure MyProc(const XMLData: string);
> XMLDoc.Active
That has no effect. The IXMLDocument is already activated when
LoadXMLData() exits.
> ThisNode:=XMLDoc.DocumentElement.ParentNode;
> // creates node equiv to .Node on TXMLDocument;
Why are you doing that? You should not be at all.
Besides, everything in TXMLDocument is directly inherited from
IXMLDocument, so whatever works in TXMLDocument also works in
IXMLDocument, and vice versa.
> MyRecursiveProcToDoStuff(ThisNode); // proc designed to accept
> TXMLDocument.Node
> end;
Why not just use the original DocumentElement node as-is? That is
what you should be doing.
> OK, so this works and doesn't crash. No apparent memory leaks,
> etc, etc. At least it works on my machine. My problem is that I
don't
> understand what it's doing and how it's doing it.
That is because you are using it wrong to begin with.
> Where's the beef? That is: With TXMLDocument I know what
> parser it's using, so on distribution I can make sure it's there.
What
> is IXMLDocument doing for a parser?
The same as TXMLDocument, as they are one and the same thing
internally.
> Were does it live and die?
IXMLDocument is a reference-counted interface. It 'dies' when there
are no more references to it.
> What is the functionality difference vs TXMLDocument.
None, other than that IXMLDocument is treated as an interface and
TXMLDocument isn't.
> That is, it crashes if I try XMLDoc.Node so that must not be
implemented.
An instance of IXMLDocument is actually an instance of TXMLDocument
behind the scenes. So the Node property is guaranteed to work in
both. If it is not, then you arte doing something else wrong in your
own code.
> Is the above process safe to do on a routine basis?
Yes.
> What is the "solid and preferred" methodology for handling XML
> in Delphi, without a form or data module?
Doesn't matter.
> My "plan B" is to create a data module on the fly, put the
TXMLDocument
> on that, then kill the DM when done but that sounds real ugly.
That is way overkill. Using IXMLDocument accomplishes the same thing
by itself.
Gambit
.. the rest of hugely helpful message removed ...
Gambit,
A huge thank you for your response to that long ago (in computer terms)
message. You just saved me a bunch of head scratching and hair pulling. And
I think my code is cleaner, too, since I'm not using TXMLDocument in it for
dynamic manipulation. It's all IXMLDocument now...
Thanks again...
WW