2011-12-02 35 views
12

Soy nuevo en delphi y ahora tengo que leer crear un xml. mi código es el siguiente:cómo crear un archivo xml en delphi

unit writexml1;

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, xmldom, XMLIntf, StdCtrls, msxmldom, XMLDoc; 

type 
    TForm1 = class(TForm) 
    XMLDocument1: TXMLDocument; 
    Button1: TButton; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 

procedure TForm1.SaveClick(Sender: TObject); 
var 
    rootName: String; 
    childNode: String; 
    attrChild: string; 
    iXml: IDOMDocument; 
    iRoot, iNode, iNode2, iChild, iAttribute: IDOMNode; 
    XMLDoc: TXMLDocument; 
begin 
    XMLDoc.Active := False; 
    XMLDoc.XML.Text := ''; 
    XMLDoc.Active := True; 
    XMLDoc.SaveToFile('C:\Documents and Settings\a\Desktop\zulfa.xml'); 
    iXml := XMLDoc.DOMDocument; 
    iRoot := iXml.appendChild(iXml.createElement('xml')); 
    iNode := iRoot.appendChild(iXml.createElement('test')); 
    iNode.appendChild(iXml.createElement('test2')); 
    iChild := iNode.appendChild(iXml.createElement('test3')); 
    iChild.appendChild(iXml.createElement('Simple calue')); 
    iNode.insertBefore(iXml.createElement('test4'), iChild); 
    iNode2 := iNode.cloneNode(True); 
    iRoot.appendChild(iNode2); 
    iAttribute := iXml.createAttribute('color'); 
    iAttribute.nodeValue := 'red'; 
    iNode2.attributes.setNamedItem(iAttribute); 
end; 

end. 

El problema es que mientras hace clic en el botón Guardar que muestra la excepción, la excepción es

Project writexml1.exe raised exception class EAccessViolation with message 
'Access violation at address 004391B9 in module writexml.exe 
+0

No está relacionado con su pregunta, pero ¿por qué está guardando el contenido de XMLDoc en un archivo antes de tener XML en él? Parece que su código nunca resultará en un archivo con xml. –

Respuesta

12

Es necesario crear la instancia XMLDoc antes de poder utilizarlo:

XMLDoc := TXMLDocument.Create(...); 
try 
    ... do stuff with XMLDOC 
finally 
    XMLDoc.Free; 
end; 
+4

Ten cuidado, sin embargo. La creación dinámica de un 'TXMLDocument' con un' nil' Owner provoca que 'TXMLDocument' actúe como una interfaz en lugar de un objeto. Llamar 'Free()' en una instancia así sería muy malo. Si desea utilizar 'Free()', debe proporcionar un Propietario no 'nil' (en cuyo caso,' Free() 'es redundante ya que el Propietario liberará' TXMLDocument' cuando el Propietario se libera)Si dinámicamente asigna un 'TXMLDocument' con un' nil' Owner, DEBE asignarlo a una variable 'IXMLDocument', en cuyo caso use' NewXMLDocument() 'en lugar de' TXMLDocument.Create (nil) '. –

+0

@remy Edito la respuesta para poner en el constructor. Pero no tengo idea de qué parámetros aprobar. De ahí el .... La respuesta original carecía de detalles. –

+1

Como cualquier otro componente, el constructor 'TXMLDocument' toma como entrada un propietario' TComponent'. Si especifica un propietario que no sea '' nil', el propietario se hará cargo de la liberación del 'TXMLDocument'. Si especifica un propietario 'nil' en su lugar,' TXMLDocument' no tendrá propietario y usted será responsable de liberarlo. Pero 'TXMLDocument' es especial en este último caso, ya que no actúa como un componente normal cuando tiene un Propietario' nil', en su lugar actúa como una interfaz contada por referencia, por lo que debe involucrar el sistema de recuento de referencias en orden para liberarlo adecuadamente –

30

su código se ve un poco complicado. Sugeriría: olvide TXMLDocument y IDOMDOCUMENT, use IXMLDOCUMENT en su lugar (la forma de utilizarlo es casi la misma que TXmlDocument pero no necesita un componente).

Este código debe demostrar, lo sencillo que es:

{...} 
Var 
    XML : IXMLDOCUMENT; 
    RootNode, CurNode : IXMLNODE; 
begin 
    XML := NewXMLDocument; 
    XML.Encoding := 'utf-8'; 
    XML.Options := [doNodeAutoIndent]; // looks better in Editor ;) 
    RootNode := XML.AddChild('XML'); 
    CurNode := RootNode.AddChild('Test'); 
    CurNode := CurNode.AddChild('Test2'); 
    CurNode.Text := 'Some Test 2 text'; 
    CurNode.Attributes['NewAttribute'] := 'Some Test2 Attribute Value'; 
    XMl.SaveToFile('C:\Documents and Settings\a\Desktop\zulfa.xml'); 
{...} 

Así es como el archivo resultante se vería así:

<?xml version="1.0" encoding="utf-8"?> 
<XML> 
    <Test> 
    <Test2 NewAttribute="Some Test2 Attribute Value">Some Test 2 text</Test2> 
    </Test> 
</XML> 

espero que esto ayude a

PD: Esta muestra solo necesita las Unidades XMLIntf y XmlDoc para que pueda ordenar su usa un poco.

11

SaveClick() declara una variable local XMLDoc que no está asignando un objeto válido TXMLDocument antes de usar i. Tiene un componente XMLDocument1 por separado en su TForm pero no lo está usando. Deshágase de XMLDoc y use XMLDocument1 en su lugar.

Además, está accediendo directamente al DOMDocument subyacente. Use los métodos propios de TXMLDocument para construir el XML en su lugar, no lo despliegue en la capa DOM a menos que necesite acceder a la funcionalidad específica del proveedor (lo que no sucede en esta situación).

Prueba esto:

procedure TForm1.SaveClick(Sender: TObject); 
var 
    iRoot, iNode, iNode2, iChild: IXMLNode; 
begin 
    XMLDocument1.Active := False; 
    XMLDocument1.XML.Text := '';  
    XMLDocument1.Active := True; 
    iRoot := XMLDocument.AddChild('xml'); 
    iNode := iRoot.AddChild('test'); 
    iNode.AddChild('test2'); 
    iChild := iNode.AddChild('test3'); 
    iChild.Text := 'Simple value'; 
    iNode.AddChild('test4', iNode.ChildNodes.IndexOf(iChild)); 
    iNode2 := iNode.CloneNode(True); 
    iRoot.ChildNodes.Add(iNode2); 
    iNode2.Attributes['color'] := 'red'; 
    XMLDocument1.SaveToFile('C:\Documents and Settings\a\Desktop\zulfa.xml'); 
    XMLDocument1.Active := False; 
end; 

que produce el siguiente código XML:

<?xml version="1.0" encoding="utf-8"?> 
<xml> 
    <test> 
    <test2 />  
    <test4 /> 
    <test3>Simple value</test3> 
    </test> 
    <test color="red"> 
    <test2 />  
    <test4 /> 
    <test3>Simple value</test3> 
    </test> 
</xml> 

Con eso dicho, utilizando IXMLDocument en lugar de TXMLDocument, como @knowledgestacker sugirió, por lo general es una mejor opción.

Cuestiones relacionadas