Generowanie pliku xml w delphi.

0

Witam.
Staram się napisać program, który miałby generować plik xml.Przy próbie zapisu pliku na dysk dostaję taki komunikat: "Access violation at address 005E7C78 in module 'Project7.exe'.Read of address 00000000". Z miejsca chciałbym zaznaczyć, że jeśli chodzi o programowanie to dopiero zaczynam swoją przygodę.
Kod programu:

unit Unit3;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Xml.xmldom, Xml.XMLIntf, Vcl.Menus,
  Xml.XMLDoc;

type
  TForm3 = class(TForm)
    MainMenu1: TMainMenu;
    SaveDialog1: TSaveDialog;
    XMLDocument1: TXMLDocument;
    File1: TMenuItem;
    New1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    SaveAs1: TMenuItem;
    Print1: TMenuItem;
    PrintSetup1: TMenuItem;
    Exit1: TMenuItem;
    N1: TMenuItem;
    N2: TMenuItem;
    procedure SaveAs1Click(Sender: TObject);
  private
    { Private declarations }
  public
    Nazwa_pliku : String;

  end;

var
  Form3: TForm3;
  LDocument: IXMLDocument;

implementation

{$R *.dfm}


procedure CreateDocument;
var
  LNodeElement, NodeCData, NodeText: IXMLNode;
begin
  LDocument := TXMLDocument.Create(nil);
  LDocument.Active := True;

  { Define document content. }
  LDocument.DocumentElement := LDocument.CreateNode('ThisIsTheDocumentElement', ntElement, '');
  LDocument.DocumentElement.Attributes['attrName'] := 'attrValue';
  LNodeElement := LDocument.DocumentElement.AddChild('ThisElementHasText', -1);
  LNodeElement.Text := 'Inner text.';
  NodeCData := LDocument.CreateNode('any characters here', ntCData, '');
  LDocument.DocumentElement.ChildNodes.Add(NodeCData);
  NodeText := LDocument.CreateNode('This is a text node.', ntText, '');
  LDocument.DocumentElement.ChildNodes.Add(NodeText);

end;


procedure TForm3.SaveAs1Click(Sender: TObject);
begin
  if SaveDialog1.Execute then
  begin
    Nazwa_pliku:=SaveDialog1.FileName;
    LDocument.SaveToFile(Nazwa_pliku);
  end;
end;

end.

Część kodu zawinąłem z tej dokumentacji: http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/TXMLDocument_use_case_(Delphi)
Piszę w najnowszym RAD Studio.
Będę wdzięczny za porady.

4

LDcokument to twoja zmienna globalna. Obiekt tworzysz natomiast w procedurze CreateDocument, natomiast SaveAll1Click - to buttton jak mniemam ma tylko savedialoga ale nigdzie nie ma odpalonej procedury CreateDocument ... Dodaj przed LDocument.SaveToFile wywołanie i powinno zadziałać :)

0

Super, działa :) Dzięki wielkie.

Jeszcze jedna kwestia, czy w jakiś sposób mogę zaimportować zawartość gotowego pliku xml do mojego programu i edytować go w kodzie źródłowym?

0

Dziękuje za link, dziękuje za pomoc.
Pozdrawiam dobry człowieku :)

2

Pamiętaj jeszcze o zwolnieniu obiektu LDocument bo będziesz miał wycieki pamięci

unit Unit3;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Xml.xmldom, Xml.XMLIntf, Vcl.Menus,
  Xml.XMLDoc;
 
type
  TForm3 = class(TForm)
    MainMenu1: TMainMenu;
    SaveDialog1: TSaveDialog;
    XMLDocument1: TXMLDocument;
    File1: TMenuItem;
    New1: TMenuItem;
    Open1: TMenuItem;
    Save1: TMenuItem;
    SaveAs1: TMenuItem;
    Print1: TMenuItem;
    PrintSetup1: TMenuItem;
    Exit1: TMenuItem;
    N1: TMenuItem;
    N2: TMenuItem;
    procedure SaveAs1Click(Sender: TObject);
  private
    LDocument: IXMLDocument;
  public
    Nazwa_pliku : String;
  end;
 
var
  Form3: TForm3;
 
implementation
 
{$R *.dfm}
 
procedure CreateDocument;
var
  LNodeElement, NodeCData, NodeText: IXMLNode;
begin
  LDocument.Active := True;
 
  { Define document content. }
  LDocument.DocumentElement := LDocument.CreateNode('ThisIsTheDocumentElement', ntElement, '');
  LDocument.DocumentElement.Attributes['attrName'] := 'attrValue';
  LNodeElement := LDocument.DocumentElement.AddChild('ThisElementHasText', -1);
  LNodeElement.Text := 'Inner text.';
  NodeCData := LDocument.CreateNode('any characters here', ntCData, '');
  LDocument.DocumentElement.ChildNodes.Add(NodeCData);
  NodeText := LDocument.CreateNode('This is a text node.', ntText, '');
  LDocument.DocumentElement.ChildNodes.Add(NodeText);
 
end;
 
procedure TForm3.SaveAs1Click(Sender: TObject);
begin
  if SaveDialog1.Execute then
  begin
    Nazwa_pliku:=SaveDialog1.FileName;
    if not Assigned(LDocument) then
        LDocument := TXMLDocument.Create(nil);
//    try
      CreateDocument;
      LDocument.SaveToFile(Nazwa_pliku);
  //   finally
    //   lDocument.Free;
   //  end;
  end;
end;
 
end.
0

Ach, to ten temat muszę jeszcze doczytać :)

Dobra widzę dodałeś kod, za pierwszym razem nie wczytał mi się w poście.

0
woolfik napisał(a):

Oczywiście, że tak. Na szybko:
http://etutorials.org/Programming/mastering+delphi+7/Part+IV+Delphi+the+Internet+and+a+.NET+Preview/Chapter+22+Using+XML+Technologies/Programming+with+the+DOM/

Ech, niestety nie bardzo łapie ten tutotrial.Używam XML Data-Binding, otwiera mi się druga zakładka ze strukturą mojego pliku xml, ale w żaden sposób nie potrafię połączyć tego z moim kodem abym mógł go edytować, a później zapisać do xml ponownie.

Kod struktury testowego pliku:


```unit testcd;

interface

uses xmldom, XMLDoc, XMLIntf;

type

{ Forward Decls }

  IXMLCatalogType = interface;
  IXMLCDType = interface;

{ IXMLCatalogType }

  IXMLCatalogType = interface(IXMLNode)
    ['{DBA5E0B7-5D02-4DD8-970A-475B3F83A87E}']
    { Property Accessors }
    function Get_CD: IXMLCDType;
    { Methods & Properties }
    property CD: IXMLCDType read Get_CD;
  end;

{ IXMLCDType }

  IXMLCDType = interface(IXMLNode)
    ['{79448E57-5C4A-4104-A4A9-D39F00A194D0}']
    { Property Accessors }
    function Get_Title: UnicodeString;
    function Get_Artist: UnicodeString;
    function Get_Price: UnicodeString;
    procedure Set_Title(Value: UnicodeString);
    procedure Set_Artist(Value: UnicodeString);
    procedure Set_Price(Value: UnicodeString);
    { Methods & Properties }
    property Title: UnicodeString read Get_Title write Set_Title;
    property Artist: UnicodeString read Get_Artist write Set_Artist;
    property Price: UnicodeString read Get_Price write Set_Price;
  end;

{ Forward Decls }

  TXMLCatalogType = class;
  TXMLCDType = class;

{ TXMLCatalogType }

  TXMLCatalogType = class(TXMLNode, IXMLCatalogType)
  protected
    { IXMLCatalogType }
    function Get_CD: IXMLCDType;
  public
    procedure AfterConstruction; override;
  end;

{ TXMLCDType }

  TXMLCDType = class(TXMLNode, IXMLCDType)
  protected
    { IXMLCDType }
    function Get_Title: UnicodeString;
    function Get_Artist: UnicodeString;
    function Get_Price: UnicodeString;
    procedure Set_Title(Value: UnicodeString);
    procedure Set_Artist(Value: UnicodeString);
    procedure Set_Price(Value: UnicodeString);
  end;

{ Global Functions }

function GetCatalog(Doc: IXMLDocument): IXMLCatalogType;
function LoadCatalog(const FileName: string): IXMLCatalogType;
function NewCatalog: IXMLCatalogType;

const
  TargetNamespace = '';

implementation

{ Global Functions }

function GetCatalog(Doc: IXMLDocument): IXMLCatalogType;
begin
  Result := Doc.GetDocBinding('Catalog', TXMLCatalogType, TargetNamespace) as IXMLCatalogType;
end;

function LoadCatalog(const FileName: string): IXMLCatalogType;
begin
  Result := LoadXMLDocument(FileName).GetDocBinding('Catalog', TXMLCatalogType, TargetNamespace) as IXMLCatalogType;
end;

function NewCatalog: IXMLCatalogType;
begin
  Result := NewXMLDocument.GetDocBinding('Catalog', TXMLCatalogType, TargetNamespace) as IXMLCatalogType;
end;

{ TXMLCatalogType }

procedure TXMLCatalogType.AfterConstruction;
begin
  RegisterChildNode('CD', TXMLCDType);
  inherited;
end;

function TXMLCatalogType.Get_CD: IXMLCDType;
begin
  Result := ChildNodes['CD'] as IXMLCDType;
end;

{ TXMLCDType }

function TXMLCDType.Get_Title: UnicodeString;
begin
  Result := ChildNodes['Title'].Text;
end;

procedure TXMLCDType.Set_Title(Value: UnicodeString);
begin
  ChildNodes['Title'].NodeValue := Value;
end;

function TXMLCDType.Get_Artist: UnicodeString;
begin
  Result := ChildNodes['Artist'].Text;
end;

procedure TXMLCDType.Set_Artist(Value: UnicodeString);
begin
  ChildNodes['Artist'].NodeValue := Value;
end;

function TXMLCDType.Get_Price: UnicodeString;
begin
  Result := ChildNodes['Price'].Text;
end;

procedure TXMLCDType.Set_Price(Value: UnicodeString);
begin
  ChildNodes['Price'].NodeValue := Value;
end;

end.
1
procedure TForm.ButtonClick(Sender: TObject);
var
  Icatalog: IXMLCatalogType;
begin
  self.XMLDocument1.Active := true;
  Icatalog := GetCatalog(self.XMLDocument1);
  Icatalog.CD.Title := 'AAAA';
  Icatalog.CD.Artist := 'BBB';
  self.XMLDocument1.SaveToFile('c:\!\cd.xml');
  self.XMLDocument.active:=false;

end;

w efekcie dostaniesz plik xml o poniżeszj treści :

<Catalog>
  <CD>
    <Title>AAAA</Title>
    <Artist>BBB</Artist>
  </CD>
</Catalog>
0

Śmiga, dzięki wielkie :)

0

Czemu nie zrobisz serializacji obiektu klasy do pliku xml? Każda technologia dziś to wspiera, ledwo 5 linii kodu. Nie wierzę, żeby w Delphi tego nie było, bo to by oznaczało, że Delphi zatrzymał się w rozwoju 25 lat temu

1 użytkowników online, w tym zalogowanych: 0, gości: 1