AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein XML XML Datenbindung und Substitution Groups

XML Datenbindung und Substitution Groups

Ein Thema von Gor1 · begonnen am 6. Mär 2015 · letzter Beitrag vom 12. Mär 2015
Antwort Antwort
Gor1

Registriert seit: 11. Mai 2011
32 Beiträge
 
Delphi 10.4 Sydney
 
#1

XML Datenbindung und Substitution Groups

  Alt 6. Mär 2015, 08:35
Hallo,

ich habe mit der XML-Datenbindung von Delphi einem XML-Schema entsprechende Klassen erzeugt. Allerdings gelingt es mir nicht, damit dann dem Schema entsprechende XML-Dateien so einzulesen, dass auch die entsprechenden Delphi-Objekte erzeugt werden. Genausowenig kann ich diese Delphi-Objekte aus dem Programm heraus erzeugen.

Das Problem liegt dabei darin, dass im Schema sogenannte Substitution Groups verwendet werden. Ich habe mal ein stark vereinfachtes Beispielschema und die mit der Datenbindung generierte Source-Datei (Beispielschema.pas) angehängt, sowie eine Beispieldatei, die mit dem Schema validiert werden kann.

Als Beispiel:
Ich habe im Programm ein Objekt vom Typ IXMLBasis erzeugt (mit NewBasis) und will jetzt ein neues Element vom Typ IXMLElement1 erzeugen. Die einzige Funktion in Beispiel.pas, mit der ich ein neues Listenelement erzeugen kann, ist die Funktion Add, die aber ein IXMLListenElement zurück liefert und kein IXMLElement1. Ich habe dann versucht, eine weitere Add-Funktion zu schreiben, die ein IXMLElement1 zurückgibt:
Delphi-Quellcode:
function TXMLBasis.Add: IXMLElement1;
begin
  Result := AddItem(-1) as IXMLElement1;
end;
Aber die Ausführung scheitert dann immer mit der Fehlermeldung EIntfCastError 'Interface nicht unterstützt' (ich nehme an, weil das AddItem(-1) ein IXMLListenElement zurück liefert, aber ich weiß nicht, wo ich beeinflussen kann, wass AddItem liefert).

Umgekehrt funktioniert das Einlesen der Beispieldatei auch nicht. Das XML kann zwar ohne Fehler gelesen werden, aber IXMLBasis.Count ist Null, obwohl ja fünf Listenelemente vorhanden sein sollten. Es wird also nicht erkannt, dass Element1, Element2 und Element3 Untertypen von Listenelement sind und deshalb auch in der Liste der Listenelemente auftauchen sollten. Geht man direkt die Childnodes des XML-Dokuments durch (also an der von der Datenbindung erzeugten Struktur vorbei), dann findet man auch die entsprechenden Einträge für die Elemente.

Hat jemand eine Idee, wie sich die Probleme lösen lassen? Oder gibt es vielleicht andere Delphi-Komponenten für die XML-Datenbindung, die solche Konstruktionen unterstützen?
Angehängte Dateien
Dateityp: 7z Beispiel.7z (2,7 KB, 17x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
39.424 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: XML Datenbindung und Substitution Groups

  Alt 6. Mär 2015, 09:04
Woher soll das XML-DOM denn deine Klassen kennen, wenn du sie him niemals mitteilst?
Schau die mal alles mit TXMLNodeCollectionClass und TXMLNodeClass in XMLDoc an.

Delphi-Quellcode:
var X: IXMLElement1;

X := TXMLElement1.Create;
// oder
X := {irgendwas mit XMLNodeCollectionClass}.Create;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu ( 6. Mär 2015 um 09:20 Uhr)
  Mit Zitat antworten Zitat
Gor1

Registriert seit: 11. Mai 2011
32 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: XML Datenbindung und Substitution Groups

  Alt 9. Mär 2015, 10:44
Aber die Klassen stehen doch in der Datei Beispiel.pas (so wie sie von der Datenbindung erzeugt wurden)?

Und wenn ich ein Element vom Typ Listenelement hinzufügen will, klappt das ja auch mit den erzeugten Klassen. Nur bei den abgeleiteten Klassen wie Element1 klappt das nicht.
Oder wie teilt man dem XML-DOM die Klassen explizit mit?

Ich habe mir TXMLNodeCollectionClass und TXMLNodeClass angeschaut, aber ich werde daraus nicht so recht schlau.
Aber wenn ich das richtig verstehe, dann erlaubt TXMLNodeCollectionClass nur Elemente von genau dem Typ, für den sie definiert wurde (also ListenElement), aber keine Elemente von abgeleiteten Typen (wie Element1).
Wenn ich (händisch beim Debuggen) dem AddChild den richtigen Knotentyp (Element1) gebe, dann wird dieser Knoten zwar erzeugt, aber beim Einfügen in die NodeCollection (in InsertInColletion) wird dann versucht, eine neue Collection zu erzeugen, da nicht erkannt wird, dass der Typ Element1 ein von Listenelement abgeleiteter Typ ist (deshalb liefert IsCollectionItem(Node) false).
Ich will aber ja erreichen, dass alle Elemente (egal ob vom Typ Element1, Element2 oder Element3) in die gleiche NodeCollection eingefügt werden (also in IXMLBasis).
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#4

AW: XML Datenbindung und Substitution Groups

  Alt 9. Mär 2015, 22:11
Das Databinding ist im allgemeinen leider eher Schrott und zudem veraltet (siehste ja an den generierten Implementierungen :>).

Wenn Du Dir auf Basis deines XML-Schemas die Klassen vom XML-Databinding erzeugen lässt, dann musst Du diese auch verwenden - da leitest Du also nichts mehr ab oder sonst irgendwas - Du bist an die generierte Implementierung gebunden. Und über die bereitgestellten, losen Methoden arbeitest Du dann damit:

- LoadBasis
Datenobjekte aus einer schemakonformen XML-Datei deserialisieren

- GetBasis
Datenobjekte aus einem bestehenden IXMLDocument deserialisieren (hier könnte Dein schemakonformes XML theoretisch auch Bestandteil einer anderen XML-Datei sein, aus der Du dann nur den generierten Teil herausserialisieren lässt.

- NewBasis
Eine neue Instanz deiner Datenobjektstruktur erzeugen lassen, um diese zu einem späteren Zeitpunkt (nach dem Arbeiten/Befüllen) wieder in ein XML-Format zu serialisieren (String/File)


Sobald Du eigene Funktionalität benötigst würde ich vom XML-Databinding weggehen und mit komplett eigenen Klassen arbeiten und mich entsprechend selbst um das Serialisieren kümmern. Sofern Du nicht mit Interfaces arbeitest, kannst Du Dir diesbezüglich mal den SvSerializer anschauen: Klick mich .

Geändert von alda ( 9. Mär 2015 um 22:15 Uhr)
  Mit Zitat antworten Zitat
Gor1

Registriert seit: 11. Mai 2011
32 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: XML Datenbindung und Substitution Groups

  Alt 10. Mär 2015, 09:03
Danke für den Tip, den SvSerializer werde ich mir mal anschauen.

Ich hatte halt gehofft, dass sich die vom Databinding generierten Schnittstellen mit vertretbarem Aufwand so modifizieren lassen, dass ich doch damit arbeiten kann. Das Schema, mit dem ich arbeiten muss, ist sehr umfangreich und deshalb ist der Aufbau einer eigenen Klassenhierarchie sehr aufwendig.
Zudem erzeugt das Databinding ja großteils sinnvolle Schnittstellen, nur mit der NodeCollection mit unterschiedlichen von einer Basisklasse abgeleiteten Objekten klappt es leider nicht.

Unter Umständen würde es für meine Zwecke auch schon reichen, wenn ich aus einem Knoten im XML-Dokument (den ich mit Childnode selektiere) z.B ein Objekt vom Typ TXMLElement1 erzeugen könnte, aber leider ist mir das bisher auch nicht gelungen.
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#6

AW: XML Datenbindung und Substitution Groups

  Alt 10. Mär 2015, 13:17
Dein Problem mit einer eigenen Implementierung sind hier halt die Interfaces - sobald Du eigene Funktionalität bereitstellen möchtest, musst Du bei der Verwendung dieser immer hin und her Casten. (Da das generierte Interface vom Databinding ja nur die aus dem Schema definierten Informationen enthält).

Danke für den Tip, den SvSerializer werde ich mir mal anschauen.

Ich hatte halt gehofft, dass sich die vom Databinding generierten Schnittstellen mit vertretbarem Aufwand so modifizieren lassen, dass ich doch damit arbeiten kann. Das Schema, mit dem ich arbeiten muss, ist sehr umfangreich und deshalb ist der Aufbau einer eigenen Klassenhierarchie sehr aufwendig.
Deine Objektstruktur muss und sollte wahrscheinlich auch nicht der Schemastruktur gleichen - die Objektstruktur sollte so aussehen, dass Sie für Deinen Anwendungszweck (im Code) am besten passt und man komfortabel damit arbeiten kann. Das Serialisieren in ein entsprechendes Format ist wiederum etwas völlige anderes und kann von der Objektstruktur wie Du Sie als Entwickler beim Coden verwendest ja durchaus abweichen.

Du hast also viele verschiedene Möglichkeiten:
- eine Übersetzung/Kapselung von Deinen Objekten in die XML-Databinding Objekte bereitstellen. Somit trennst Du "Deine" Objektstruktur von der des XML-Databindings und kannst auf der einen Seite komfortabel mit "Deinen" Objekten arbeiten und auf der anderen Seite immer Schemakonform speichern
- eine Übersetzung von Deinen Objekten in das XML-Format manuell vornehmen
- eine Übersetzung von Deinen Objekten in das XML-Format von einer anderen Bibliothek übernehmen lassen, bei der das z.B. über Attribute und RTTI läuft (z.B. den SvSerializer)
  Mit Zitat antworten Zitat
Gor1

Registriert seit: 11. Mai 2011
32 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: XML Datenbindung und Substitution Groups

  Alt 11. Mär 2015, 08:41
Zitat:
Du hast also viele verschiedene Möglichkeiten:
- eine Übersetzung/Kapselung von Deinen Objekten in die XML-Databinding Objekte bereitstellen. Somit trennst Du "Deine" Objektstruktur von der des XML-Databindings und kannst auf der einen Seite komfortabel mit "Deinen" Objekten arbeiten und auf der anderen Seite immer Schemakonform speichern
- eine Übersetzung von Deinen Objekten in das XML-Format manuell vornehmen
- eine Übersetzung von Deinen Objekten in das XML-Format von einer anderen Bibliothek übernehmen lassen, bei der das z.B. über Attribute und RTTI läuft (z.B. den SvSerializer)
Das Problem ist ja, dass die von der Datenbindung generierten Objekte beim einlesen einer zum Schema passenenden Datei schon gar nicht gefüllt werden, deshalb kann ich diese auch nicht verwenden (unabhängig davon, wie meine interne Struktur dann aussieht).

Den Sv-Serializer habe ich mal ausprobiert, leider habe ich da das Problem, dass bei der Serialisierung die Properties alle in Elemente des XML-Knotens umgewandelt werden, das Schema erwartet aber Attribute. Gibt es da vielleicht eine Möglichkeit, um für eine Property zu bestimmen, ob sie als Element oder als Attribut interpretiert werden soll?

Ansonsten bleibt mir wohl wirklich nur, die Übersetzung manuell vorzunehmen.
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#8

AW: XML Datenbindung und Substitution Groups

  Alt 11. Mär 2015, 19:52
Das Problem ist ja, dass die von der Datenbindung generierten Objekte beim einlesen einer zum Schema passenenden Datei schon gar nicht gefüllt werden, deshalb kann ich diese auch nicht verwenden (unabhängig davon, wie meine interne Struktur dann aussieht).
Dann hast Du was falsche gemacht. Wie liest Du die XML-Datei denn ein? Poste mal bitte einen Snippet. Out of the Box (also mit den generierten Implementierungen) sollte erstmal alles reibungslos laufen - vorausgesetzt Du liest es über die bereitgestellten Methoden des Databindings ein ;D


Den Sv-Serializer habe ich mal ausprobiert, leider habe ich da das Problem, dass bei der Serialisierung die Properties alle in Elemente des XML-Knotens umgewandelt werden, das Schema erwartet aber Attribute. Gibt es da vielleicht eine Möglichkeit, um für eine Property zu bestimmen, ob sie als Element oder als Attribut interpretiert werden soll?
Ja ich glaube er kann das nicht, bin mir aber nicht sicher. Konnte zumindest auf die schnelle kein vorhandenes Attribut finden, mit dem das zu steuern wäre. Ich arbeite selbst auch an einer eigenen Implementierungen da mir die bestehenden Bibliotheken nicht gefallen und zu unflexibel sind, allerdings aufgrund zu wenig Zeit leider noch under construction

Ansonsten gibt es noch eine Implementierung in DSharp, die allerdings auch nicht komplett ist (auf der basiert auch meine eigene). Da blickt man, im vergleich zum SvSerializer auch wenigstens durch und kann manuell recht schnell etwas ändern: Klick mich (DSharp.Core.XmlSerialization.*)

Geändert von alda (11. Mär 2015 um 19:55 Uhr)
  Mit Zitat antworten Zitat
Gor1

Registriert seit: 11. Mai 2011
32 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: XML Datenbindung und Substitution Groups

  Alt 12. Mär 2015, 08:22
Zitat:
Dann hast Du was falsche gemacht. Wie liest Du die XML-Datei denn ein? Poste mal bitte einen Snippet. Out of the Box (also mit den generierten Implementierungen) sollte erstmal alles reibungslos laufen - vorausgesetzt Du liest es über die bereitgestellten Methoden des Databindings ein ;D
Ich glaube, es gab da ein Mißverständnis. Mein Problem ist gerade, dass aufgrund der Verwendung von Substitution Groups im Schema der von der Datenbindung erzeugte Code nicht funktioniert, also sich damit Schema-konforme Dateien weder sinnvoll einlesen noch neu erzeugen und dann schreiben lassen.
Ich habe die XML-Datenbindung auch früher schon mit anderen (einfacheren) Schemata benutzt und hatte da nie Probleme, aber da wurden eben keine Substitution Groups verwendet.

Wenn ich bei dem Beispiel, das ich gepostet habe, mit
Delphi-Quellcode:
procedure Einlesen;
var iBasis: IXMLBasis;
begin
  iBasis := LoadBasis('Beispieldatei.xml');
end;
die XML-Datei einlese, dann sollte ja iBasis Listenelemente vom Typ IXMLListenElement enthalten (bzw. eben von den von IXMLListenElement abgeleiteten Typen IXMLElement1, ...). Diese Liste ist aber leer, iBasis.Count ist Null. Die Datenbindung schafft es leider nicht, ein IXMLElement1 einzulesen und in die Liste einzuhängen.
Umgekehrt funktioniert es eben auch nicht (bzw. ich habe es nicht hinbekommen), ein neues Element vom Typ IXMLElement1 zu erzeugen und unter iBasis einzufügen.
Ich habe auch versucht, XMLDocument so zu modifizieren, dass eine Funktion Add: IXMLElement1, die ich in IXMLBasis eingefügt habe, auch ein IXMLElement1 erzeugt, aber dabei bin ich immer an einer Fehlermeldung "...Interface wird nicht unterstützt" gescheitert.
  Mit Zitat antworten Zitat
alda

Registriert seit: 24. Mär 2014
Ort: Karlsruhe
93 Beiträge
 
Delphi XE6 Architect
 
#10

AW: XML Datenbindung und Substitution Groups

  Alt 12. Mär 2015, 21:55
Das hab ich in der Tat überlesen, danke für den Hinweis Hätte nicht gedacht, dass er das (die SubstitutionGroups) überhaupt in den generierten Klassen abbilden kann, aber ich werd das morgen gleich mal bei mir testen, das interessiert mich jetzt
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf