Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Prism XMLSerializer: Verschachtelte XML-Dateien mit Arrays? (https://www.delphipraxis.net/83987-xmlserializer-verschachtelte-xml-dateien-mit-arrays.html)

Alexander 9. Jan 2007 19:21


XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Hallo DPler,
ich habe gerade ein wenig über XMLSerializer gelesen und bin zu dem Entschluss gekommen: Das brauche ich!
Wie sehr müsste man sich doch abmühen, eine große XML-Datei per Hand über System.XML zu zerpflücken und in eine Klasse zu schieben.

Doch klappt Serialisierung auch bei tief verschachtelten XML-Dateien, die zudem noch mit Array's in verschiedenen Ebenen gespickt sind? Sprich wie flexibel ist Serialisierung?
Mal ein Beispiel (die Struktur):
XML-Code:
<config>
  <einstellung1>
   <foo_1 name="">blupp</foo_1>
   <foo_2>irgendetwas anderes</foo_2>
  </einstellung1>
  <Geoeffnete_Dateien>
    <datei>
     <pfad></pfad>
     <datum></datum>
     <nocheinArray>
       <eintrag></eintrag>
       <eintrag></eintrag>
     </nocheinArray>
    </datei>
    <datei>
     <pfad></pfad>
     <datum></datum>
     <nocheinArray>
       <eintrag></eintrag>
       <eintrag></eintrag>
     </nocheinArray>
    </datei>
  </Geoeffnete_Dateien>
</config>
Das ist jetzt irgendeine XML-Struktur, die ich mir gerade mal so ausgedacht habe. Wie sinnvoll das nun ist, spielt jetzt mal keine Rolle :).
Allerdings stehe ich gerade auf dem Schlauch, den Source Code zu schreiben, der solch eine XML-Struktur erzeugt. Könnt ihr mir da auf die Sprünge helfen?

CDATA-Abschnitte und Attribute werden doch sicherlich auch unterstützt, oder? Sonst kann ich das nämlich vergessen :(.
Gut Attribute wäre nicht ganz so wichtig, da könnte man einzelen Nodes von machen, das wäre aber nicht so schick :(.

Ich freue mich schon auf eure Unterstützung und probiere der Weil selbst ein wenig rum.

Alexander

Elvis 9. Jan 2007 20:39

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
lasse einfach mal XSD.exe darüber laufen um eine xsd-Datei zu kriegen.
Lasse es nochmal darüber laufen, diesmal mit dem schalter /c um Klassen zu bekommen.
Diese werden in C# sein, um Delphi Klassen zu kriegen müsstest du ihm sagen wo er den CodeDom findet, da sich der Delphi Compiler nicht vollständig ins Framework installiert. Da habe ich irgendwie keine Lust das jetzt rauszukramen.
Eine C# ClassLib zu konsumieren ist ja auch OK, right? ;)

Khabarakh 9. Jan 2007 20:40

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Zitat:

Zitat von Alexander
Doch klappt Serialisierung auch bei tief verschachtelten XML-Dateien, die zudem noch mit Array's in verschiedenen Ebenen gespickt sind? Sprich wie flexibel ist Serialisierung?

So flexibel, dass du (naja, fast :zwinker: ) jedes XML-Schema in xsd.exe werfen kannst und dann einen fertigen Quelltext zurückbekommst, dessen Klassen sich genau nach jenem Schema serialisieren lassen ;) . Dein Beispiel sollte sich also buchstäblich in Klassen, die genau diesen XML-Code generieren, umsetzen lassen.

Alexander 10. Jan 2007 17:41

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Ich habe mir gerade mal XSD.exe angeschaut und bin schwer begeistert. Wenn der mir noch Delphi.NET-Source erzeugen würde, wäre es natürlich perfekt.
Gut ich habe den Code noch nicht ausprobiert (gerade kein VS installiert), aber das was ich an C# Code gesehen habe, ist echt :thumb:

Was mich besonders beeindruckt, ist dass es mit xsd.exe noch einfacher ist als ich eh schon dachte (bzw. vermutete). Jetzt muss man sich nicht mal mehr die Klassen zusammenschreiben.

Die Schema Datei wird nur zur Erzeugung der Klassen gebraucht, oder? Die verstehe ich nämlich noch nicht ganz.

Ich werde zwar sicherlich noch die ein oder andere Frage dazu stellen, möchte mich auf jeden Fall aber schon mal ganz nett bei euch beiden bedanken :P

Alexander 10. Jan 2007 17:57

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Mit dem folgenden Aufruf kann man auch Delphi Code erzeugen:
XSD.exe c:\tt.xsd /l:Borland.Delphi.DelphiCodeProvider,DelphiProvider ,Version=10.0.4143.0,Culture=neutral,PublicKeyToke n=91d62ebb5b0d1b1b /c /o:c:\

Das Staunen steigert sich so langsam noch mehr :mrgreen:

Alexander 12. Jan 2007 18:22

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Soooo jetzt habe ich noch mal ne Frage und zwar möchte ich gerne System.Drawing.Color serialisieren.
Leider wird dabei nichts abgespeichert. Gibt es dabei einen Trick oder soll ich einfach einen String nehmen? und die RGB Werte abspeichern?

Alexander 2. Feb 2007 14:43

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Ich habe dazu noch einmal eine kleine Frage und zwar möchte ich einen String als CDATA Abschnitt speichern / serialisieren.
Leider konnte ich noch nicht herausfinden, wie ich das mit Delphi schaffen kann.
Oder soll ich einfach die entsprechende CDATA-Kennzeichnung um den String schmeißen und dann serialisieren (was ich ziemlich unelegant finden würde :?).

Da gibt es doch sicherlich eine einfache Möglichkeit, oder?

Danke :)

Elvis 4. Feb 2007 20:17

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Zitat:

Zitat von Alexander
Da gibt es doch sicherlich eine einfache Möglichkeit, oder?

Dich hätte ich fast vergessen...

Du kannst dir ja den Code hier so anpassen dass er mit Delphi.Net oder Chrome/.Net1.1 läuft.
Du benutzt einfach die Klasse CData anstatt String und beim Serialisieren bekommst du eine CData section.

Delphi-Quellcode:
uses
  System.Xml.*;
 
type
  CData = public sealed class(IXmlSerializable,
                              IComparable<String>,
                              IEquatable<String>,
                              IComparable<CData>,
                              IEquatable<CData>)
  public
    class operator Implicit(value : String) : CData;
    class operator Implicit(value : CData) : String;

    class operator Equal(left: CData; right: String) : Boolean;
    class operator Equal(left: CData; right: CData) : Boolean;

    method Equals(obj : Object) : Boolean; override;
    method Equals(obj : CData) : Boolean;
      implements IEquatable<CData>.Equals;
    method CompareTo(obj: CData): Integer;
      implements IComparable<CData>.CompareTo;

    constructor; empty;
    constructor(text : String);
  private
    method Equals(other: String): Boolean;
      implements IEquatable<String>.Equals;
    method CompareTo(other: String): Integer;
      implements IComparable<String>.CompareTo;

    Text : String;

    method WriteXml(writer: XmlWriter);
    method ReadXml(reader: XmlReader);
    method GetSchema: XmlSchema; empty;
  end;
 
implementation

constructor CData(text : String);
begin
  self.Text := text;
end;

method CData.ReadXml(reader: XmlReader);
begin
  Text := reader.ReadString();
end;

method CData.WriteXml(writer: XmlWriter);
begin
  writer.WriteCData(Text);
end;

class operator CData.Implicit(value : String) : CData;
begin
  exit(new CData(value));
end;

class operator CData.Implicit(value : CData) : String;
begin
  exit(value.Text);
end;

method CData.Equals(obj : Object) : Boolean;
begin
  if ReferenceEquals(self, obj)
     or ReferenceEquals(Text, obj) then
    exit(true)
  else if obj is CData then
    with e := CData(obj) do
      exit(Equals(e))
  else if obj is IEquatable<String> then
    with e := IEquatable<String>(obj) do
      exit(e.Equals(Text))
  else if obj is IEquatable<CData> then
    with e := IEquatable<CData>(obj) do
      exit(e.Equals(self));
end;

method CData.Equals(other: String): Boolean;
begin
  exit(Text.Equals(other));
end;

method CData.Equals(obj : CData) : Boolean;
begin
  exit(self = obj);
end;

method CData.CompareTo(other: String): Integer;
begin
  exit(Text.CompareTo(other));
end;

method CData.CompareTo(obj: CData): Integer;
begin
  if not assigned(obj) then
    exit(String.Compare(Text, String(nil)))
  else
    exit(String.Compare(Text, obj.Text))
end;

class operator CData.Equal(left: CData; right: String) : Boolean;
begin
  if not assigned(left)
     and not assigned(right) then
    exit(true)
  else if not assigned(left) then
    exit(String.IsNullOrEmpty(right))
  else
    exit(left.Equals(right));
end;

class operator CData.Equal(left: CData; right: CData) : Boolean;
begin
  if ReferenceEquals(left, right) then
    exit(true)
  else if assigned(left) and assigned(right) then
    exit(String.Equals(left.Text, right.Text))
  else if not assigned(left) then
    exit(String.Equals(right.Text, String(nil)))
  else
    exit(String.Equals(left.Text, String(nil)));
end;

Alexander 5. Feb 2007 16:01

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Danke Robert. Aber so ganz habe ich das noch nicht verstanden.

Mal ein Ausschnitt so wie ich es bisher ohne CDATA gemacht habe. Gespeichert wird ein String und eine Arraylist von TFoo.
Delphi-Quellcode:
  TXmlData = class
  public
    test : String;
    [System.Xml.Serialization.XmlElementAttribute('Foo', TypeOf(TFoo), Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    Foo : ArrayList;
  end;

procedure TSteuerdateiReader.saveData;
var
  Ser : XmlSerializer;
  Writer : StreamWriter;
begin
  Writer := StreamWriter.Create(XmlPath);
  Ser := XmlSerializer.Create(typeOf(TXmlData));
  try
    Ser.Serialize(Writer, data);
  finally
    Writer.Close;
    Writer.Free;
    Ser.Free;
  end;
end;

procedure TSteuerdateiReader.loadData;
var
  Ser : XmlSerializer;
  Reader : StreamReader;
begin
  Reader := StreamReader.Create(XmlPath);
  Ser := XmlSerializer.Create(typeOf(TXmlData));
  try
    data := Ser.Deserialize(Reader) as TXmlData;
  finally
    Reader.Close;
    Reader.Free;
    Ser.Free;
  end;
end;
Jetzt müsste ich deinen Code nehmen, einbinden und im Code String durch CData ersetzen und "schon" klappt es?
Das wäre ja einfach. Wäre, weil ich leider deinen Code nicht nach Delphi konvertiert bekomme. Vielleicht kannst du mir da noch helfen?
Wird beim Serialisieren WriteXml aufgerufen?

Eine Möglichkeit ähnlich der Serialisierung von ArrayListen o.ä. gibt es nicht, oder?

Elvis 5. Feb 2007 19:20

Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
 
Zitat:

Zitat von Alexander
Jetzt müsste ich deinen Code nehmen, einbinden und im Code String durch CData ersetzen und "schon" klappt es?
Das wäre ja einfach.

Exakt! :)
Delphi-Quellcode:
Wäre, weil ich leider deinen Code nicht nach Delphi konvertiert bekomme. Vielleicht kannst du mir da noch helfen?
Er benutzt halt .Net 2.0, ich dachte du würdest einfach die generischen Interfaces rausnehmen und den rest zu DfN konvertiert kriegen.
No prob, ich bin in etwa 1h zu Hause, dann konvertiere ich es zu Chrome/.Net1.1. Das kannst du ja ganz easy benutzen oder die Syntaxunterschiede selbst übersetzen. (Habe kein DfN ;) )
Zitat:

Wird beim Serialisieren WriteXml aufgerufen?
Jupp, das ist der Teil, der IXmlSerializable implementiert. ;)
Zitat:

Eine Möglichkeit ähnlich der Serialisierung von ArrayListen o.ä. gibt es nicht, oder?
Nein, einer der Beta Builds von .Net 2.0 hatte es, aber die Hirnies aus Redmond haben es bis zur Final wieder entfernt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:22 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz