Generowanie pliku xml w delphi.

Generowanie pliku xml w delphi.
Fausto
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:32
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:

Kopiuj
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.

woolfik
  • Rejestracja:ponad 17 lat
  • Ostatnio:około godziny
  • Postów:1595
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ć :)

Fausto
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:32
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?

edytowany 1x, ostatnio: flowCRANE
woolfik
  • Rejestracja:ponad 17 lat
  • Ostatnio:około godziny
  • Postów:1595
Fausto
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:32
0

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

edytowany 1x, ostatnio: flowCRANE
woolfik
  • Rejestracja:ponad 17 lat
  • Ostatnio:około godziny
  • Postów:1595
2

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

Kopiuj
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.
edytowany 3x, ostatnio: woolfik
KA
lDocument.Free; chyba FreeAndNill aby w dokumencie nalazły się aktualne dane (jak metoda jest dostępna nie mam teraz dostępu i nie mogę sprawdzić a jak nie to trzeba przypisać nil).
Fausto
Przypisałem nil i działa.
woolfik
chyba nawet wcale nie trzeba bo nie zauważyłem, że to interfejs :P
Fausto
mniejsza o to, działa.Dziękować. :)
flowCRANE
W tym kodzie są same interfejsy, więc nie trzeba nic zwalniać. :]
Fausto
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:32
0

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

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

edytowany 1x, ostatnio: Fausto
Fausto
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:32
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:

Kopiuj

```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.
edytowany 1x, ostatnio: Fausto
GS
  • Rejestracja:ponad 14 lat
  • Ostatnio:około 2 godziny
1
Kopiuj
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 :

Kopiuj
<Catalog>
  <CD>
    <Title>AAAA</Title>
    <Artist>BBB</Artist>
  </CD>
</Catalog>
edytowany 1x, ostatnio: grzegorz_so
Fausto
  • Rejestracja:prawie 8 lat
  • Ostatnio:ponad rok
  • Postów:32
0

Śmiga, dzięki wielkie :)

edytowany 2x, ostatnio: flowCRANE
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

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)