![]() |
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:
Das ist jetzt irgendeine XML-Struktur, die ich mir gerade mal so ausgedacht habe. Wie sinnvoll das nun ist, spielt jetzt mal keine Rolle :).
<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> 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 |
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? ;) |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
|
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 |
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: |
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? |
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 :) |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
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; |
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:
Jetzt müsste ich deinen Code nehmen, einbinden und im Code String durch CData ersetzen und "schon" klappt es?
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; 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? |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Delphi-Quellcode:
Er benutzt halt .Net 2.0, ich dachte du würdest einfach die generischen Interfaces rausnehmen und den rest zu DfN konvertiert kriegen.
Wäre, weil ich leider deinen Code nicht nach Delphi konvertiert bekomme. Vielleicht kannst du mir da noch helfen?
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:
Zitat:
|
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Liste der Anhänge anzeigen (Anzahl: 1)
Hab' mir doch etwas Zeit gelassen.
Ich habe ein Archiv mit der Klasse und 2 Kompilaten (1.1 und 2.0) angehängt. Falls du es selbst kompilieren willst: Als Compiler empfehle ich dir die Mono version ( ![]() Kompiliert wird für jeweils eine bestimmte .Net Version so:
Code:
chrome.exe SampleLib.chrome /frameworkversion=v1.1.4322 out=1.1
chrome.exe SampleLib.chrome /frameworkversion=v2.0.50727 out=2.0 |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Cool Danke, Robert!
Ich werde mir das nachher zu Hause mal in Ruhe anschauen. Nachtrag: Im Prinzip hatte ich es so eigentlich auch. Nur konnte Delphi merkwürdiger Weise nicht von IXmlSerializable ableiten :stupid:. Ich werde es nachher noch mal probieren. Oder noch besser lasse es einfach sein und nehme für so was wirklich den Chrome- oder C#-Compiler ;). |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Zitat:
|
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Ich habe jetzt einfach mal zum Testen deine fertige Lib verwendet.
Und es scheint zur Hälfte zu funktionieren :). In der XML-Datei soll ein SQL-Statement abgespeichert werden. Dieses wird gleich am Anfang an eine (Fremd-) Komponente (Win32, ActiveX) weitergegeben. Theoretisch mit dem CDATA-Abschnitt ja kein Problem. Bisher habe ich zum Testen ohne CDATA gearbeitet - hat mit der Komponente funktioniert. Um die gleichen SQL-Statements habe ich nun ein <![CDATA[ und ein ]]> geschrieben. Dann das Object (CData statt String) angepasst und *wuppdi* hätte es funktionieren müssen. Die verwendete Komponente sagt mir den folgenden Fehler: Zitat:
SQL-Code:
Genau dieses Statement hat zu vor funktioniert.
---------------------------
--------------------------- SELECT Artikel.[Artikel-Nr], Artikel.Artikelname, Artikel.[Lieferanten-Nr], Artikel.Lagerbestand FROM Artikel ORDER BY Artikel.[Artikel-Nr] where (Artikel.[Artikel-Nr] between 1 and 10) --------------------------- OK --------------------------- Kann es sein, dass die Komponente irgendwelche Codierungen verwechselt? Hast du eine Idee, woran das liegen könnte? Besten Dank nochmals, Alexander |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Zitat:
Sehr dumm ist es, wenn die Komponente ein Object schluckt und dann einfach anhand des Typen irgendwas friemelt. Deshalb würde ich einen Cast auf String empfehlen. Außerdem ist es nicht dumm der XML Datei ein Unicode-Format zu geben um Konvertierungsprobleme gleich von Anfang an auszuschließen. Es ist leider nicht möglich den inneren Text öffentlich zugänglich zu machen ohne Inkonsistenzen zu riskieren. CData muss als primitiver Typ auftreten, auch wenn es eigentlich nur ein Wrapper um einen String ist. btw: Diese eckigen Klammern gibt es eigentlich nur in den beiden komischen Accessversionen, die Microsoft DBMS nennt: Dem serverbasierten Access namens SqlServer und dem clientbasierten Access namens Jet/Access. :mrgreen: Bei einen richtigen/normalen DBMS werden Bezeichner, die gegen die Regeln normaler Bezeichner des DBMS verstoßen, in Anführungszeichen ( #34 ) eingeschlossen. Wobei die Bezeichner dann auch case sensitive sind! [1]der Teil vor dem letzten Punkt in deinen Unitnamen, DfN-Namespaces sind, höflich ausgedrückt, komisch |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Zitat:
Zitat:
Zitat:
Nachtrag: Zum Source: Die Lade und Speicher Methode und ein Test-Object stehen ja oben schon. Und so setze ich einfach das SQL-Statement:
Delphi-Quellcode:
Das war's im Prinzip.
Cube.DCRecordSource := aStatement.Sql;
|
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Zitat:
Zitat:
Wirkliche Klarheit wird dir nur der Debugger liefern können. Einfach mal schauen, was in CData drin steht. Da CData ToString überschreibt sollte der Inhalt zu sehen sein ohne es aufklappen zu müssen. :) |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Ich habe es jetzt noch mal mit dem Chrome-Compiler neu kompiliert (nun auch mit nem ordentlichen Namespace).
Zitat:
Zitat:
(Hast du dir dein Wissen eigentlich selbst beigebracht? ) Zitat:
Es handelt sich im Übrigen um diese Komponente: ![]() Allerdings in einer etwas älteren Version (2.5). |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Zitat:
Zitat:
Denn bei einem Zeilenumbruch geht definitiv der Cr (#13) flöten, wenn man nicht explizit über einen XmlReader deserialisiert... Hier mal zur Anschauung
Delphi-Quellcode:
Interessant ist was dabei rauskommt:
type
SampleClass = public class public property CDataString : CData; end; class method ConsoleApp.Main; const fileName = 'data.xml'; const sampleString = 'SELECT A, B'#13#10 'FROM C'; method ShowWhiteSpaces(value : String); begin Console.WriteLine(value.Replace(#32, '[Space]') .Replace(#9, '[Tab]') .Replace(#13#10, '[CrLf]') .Replace(#13, '[Cr]') .Replace(#10, '[Lf]')); end; begin var serializer := new XmlSerializer(typeof(SampleClass)); if not File.Exists(fileName) then using stream := new FileStream(fileName, FileMode.Create) do using writer := new XmlTextWriter(stream, Encoding.UTF8) do begin serializer.Serialize(writer, new SampleClass(CDataString := sampleString)); end; // mit reader using stream := new FileStream(fileName, FileMode.Open) do using reader := new XmlTextReader(stream) do with s := serializer.Deserialize(reader) as SampleClass do ShowWhiteSpaces(s.CDataString); // ohne reader using stream := new FileStream(fileName, FileMode.Open) do with s := serializer.Deserialize(stream) as SampleClass do ShowWhiteSpaces(s.CDataString); Console.ReadLine(); end; Output SELECT[Space]A,[Space]B[CrLf]FROM[Space][Space][Space]C SELECT[Space]A,[Space]B[Lf]FROM[Space][Space][Space]C |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Das war's auch nicht.
Es sind keine lf's, tabs etc. im String drin. Leider :sad:. Ich habe gerade mal versucht, das SQL-Statement mit beiden Varianten auszulesen, um den String vergleichen zu können.
Delphi-Quellcode:
Leider bekomme ich da zur Laufzeit einen Fehler:
TStatement = class
public Connection : TDataBaseConnection; [XmlElement('Sql')] Sql2 : String; Sql : CDataLib.CData; end; Zitat:
Delphi-Quellcode:
(TStatement taucht in TData wieder auf).
Ser := XmlSerializer.Create(typeOf(TData));
Ist das nicht möglich oder bin ich da auf dem Holzweg? |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Aber als Randbemerkung: Es ist ziemlich böse dem Serializer öffentliche Felder vorzuwerfen, vor allem wenn diese Felder Collections sind. edit: Du hast 2-mal das gleiche Element! Sql und Sql2 sind beide das Element Sql. Das ist nicht erlaubt. |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Beide Strings sind 100% identisch. Auf der einen Seite verwundertlich, auf der anderen wieder um nicht. Es liegt also scheinbar nicht an der Art des Deserialisierens, sondern an etwas anderem. Die große Frage ist nur noch, an was :zwinker: Zitat:
Aber ich hänge die komplette Unit noch mit einer XML-Datei an. Vielleicht kannst du ja noch mal ein Blick reinwerfen. Ich sehe beim besten Willen den Fehler nicht. Zitat:
Nachtrag: Zur Erklärung des Codes: Die verwendete Komponente ist eine Art Grid Komponente. Das SQL-Statement, die Verbindung und die Verteilung der Spalten etc. stehen in der XML-Datei (DAT). Es soll alles ausgelesen und der Komponente übergeben werden. Hört sich einfach an, ist es ja eigentlich auch, nur macht die Komponente ja scheinbar was es will. Debuggen bringt nichts. Wenn ich mir den RecordSource (SQL-Text) in der Komponente anschaue, steht dort exakt das, was auch in der XML-Datei steht.... |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Ich habe das ganze jetzt noch mal komplett mit Chrome ausprobiert. Da funktioniert es genau so wie es soll.
Scheint wohl ein Bug zu sein :wall: . Sind vielleicht Chrome Assemblies nicht 100%zig mit Delphi kompatibel? Kann ich mir allerdings nicht vorstellen (ist ja auch nur CLR). |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Wenn es geht ist doch gut, du kannst die Chrome-Lib ja später per ILMerge zu deinem Delphi Binary ranklatschen. Zitat:
Ich mus aber zugeben, dass ich die Lib nur mit PE Verify von 2.0 getestet habe. Das ist normalerweise viel genauer als das aus 1.1 und da ich nur die mscorelib von 1.1 nahm, hätte e mir auch gezeigt ob ich Dinge aus 2.0 benutze. |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Zitat:
Noch weiß ich nicht genau, was es mir bringt, dass es unter Chrome klappt :lol:. Ich könnte die gesamte Klasse nach Chrome portieren und dann in Delphi einbinden. Oder das gesamte Projekt (so wie du es in dem anderen Thread vorgeschlagen hast) als Lib in Chrome einbinden. Mal schauen. |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Hallo :)
ich bin nun dazu gekommen, die gesamte Klasse, in der ich die XML-Daten lade, speichere und verwende nach Chrome zu portieren. Dann mit dem Mono Compiler compiliert und in Delphi.NET eingebunden. Gleicher Fehler :sad:. Ich werde das Projekt wohl erstmal in Delphi weiter entwickeln müssen, da sich das mit dem Erwerb von Chrome wohl etwas in die Länge zieht (meine Bank kann leider nichts mit von RemObjects angegebenen ABA- und LLC-Nummer anfangen, ich auch nicht :mrgreen:. Meine Bank braucht unbedingt ne IBAN/BIC Nummer -> Remobjects sagt: Die angegebene Nummern würden reichen :wall:). |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Frage es direkt in remobjects.non-tech oder remobjects.public.chrome. Dort wird dann Marc drüber stolpern und er regelt solche Dinge sehr unbürokratisch. (Ist ja auch seine Kohle, die du loswerden willst. :mrgreen: ) |
Re: XMLSerializer: Verschachtelte XML-Dateien mit Arrays?
Zitat:
Danke für den Tip :zwinker: . |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz