Öttinger
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Hallo miteinander, angenommen es liegt eine XML-Datei der Form txt = "<data>
<part>
<elem keyref=\"a\"/>
<elem keyref=\"b\"/>
</part>
<elements>
<elem key=\"a\" name=\"abc\"/>
<elem key=\"a\" name=\"abc\"/>
</elements>
</data>" vor, und man möchte beim Einlesen oder auch nach dem Einlesen die Elemente die mittels keyref auf ein Element mit dem Identifizierer key verweisen durch ersetzen. Kann mir jemand an einem Beispiel zeigen, wie soetwas in XML Parsern einer bel. Programmiersprache gelöst ist ohne das man selbst eine Methode dafür zu schreiben hat?
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Durch *was* denn ersetzen? 😉 Bitte ergänze das noch mal und gib bitte mal ein Beispiel an!
|
Öttinger
(Themenstarter)
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Hi, durch eben dieses ersetzen, also beim Lesen von <part>
<elem keyref=\"a\"/>
<elem keyref=\"b\"/>
</part> sollte dann folgendes gelesen werden: <part>
<elem key=\"a\" name=\"abc\"/>
<elem key=\"a\" name=\"abc\"/>
</part>
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
UnD Du bist Dir sicher, dass Du das in der XML-Struktur so haben willst? Soll die so wieder zurück geschrieben werden? Erkläre doch bitte mal den Kontext und um was er Dir eigentlich geht! Ich vermute hier ein XY-Problem - und bevor ich Dir zeige, wie das geht, fände ich es besser, ich erfahre, was Du eigentlich erreichen willst 😉 Das spart Mühe, Nerven und führt für Dich vermutlich zu einem besseren und eleganteren Ergebnis.
|
Lasall
Ehemalige
Anmeldungsdatum: 30. März 2010
Beiträge: 7723
|
Hi Öttinger, mit Vala sieht ein Prototyp mit libxml2 folgendermaßen aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 | static void main (string[] args) {
for (var i = 1; i < args.length; ++i)
parse_file (args[i]);
}
void parse_file (string filename) {
var doc = Xml.Parser.parse_file (filename);
var root_node = doc->get_root_element();
Xml.Node* part_node = null;
Xml.Node* elements_node = null;
for (Xml.Node* node = root_node->children; node != null; node = node->next) {
if (node->type != Xml.ElementType.ELEMENT_NODE)
continue;
switch (node->name) {
case "part":
part_node = node;
break;
case "elements":
elements_node = node;
break;
default:
break;
}
}
if (part_node != null && elements_node != null)
process_keys (part_node, elements_node);
delete doc;
}
void process_keys (Xml.Node* part_node, Xml.Node* elements_node) {
for (Xml.Node* node = part_node->children; node != null; node = node->next) {
if (node->type != Xml.ElementType.ELEMENT_NODE)
continue;
print (node->get_prop ("keyref") + ": " + lookup_name (node->get_prop ("keyref"), elements_node) + "\n");
}
}
string? lookup_name (string keyref, Xml.Node* elements_node) {
for (Xml.Node* node = elements_node->children; node != null; node = node->next) {
if (node->type != Xml.ElementType.ELEMENT_NODE)
continue;
if (node->get_prop ("key") == keyref)
return node->get_prop ("name");
}
return null;
}
|
Befehl zum Kompilieren:
valac --pkg libxml-2.0 test.vala Ein objektorientierter Ansatz lohnt sich hier durchaus, um dann auch die Ausgabe wieder als XML zu schreiben. (Bleibt dem Leser überlassen 😉 .) Wenn du mehr Informationen über die Sortierung hast, lässt sich die lookup_name -Funktion deutlich verbessern (momentan läuft das suboptimal in O(n²), auf Kosten von Speicherplatz kann man mit Hashing noch mindestens die Konstante runterbiegen (Laufzeit sparen)). Gruss
Lasall
|
Öttinger
(Themenstarter)
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Dann hole ich einmal etwas weiter aus. Ich will in R, Funktionen so allgemein vorhalten, dass ich sie anhand einer Konfigurations-Datei, welche grob gesprochen die Strucktur von Daten definiert, die untersucht werden sollen, auf eben diese Daten anwenden kann. Nun liegt für mich die Schwierigkeit darin vom Wörtchen allgemein zur konkreten Umsetzbarkeit eine Brücke zuschlagen. Mir geht es nämlich so, dass ich immer ersteinmal für jeden Schritt in der Planung mir auch die praktische Umsetzbarkeit vorstellen können und in Gedanken durch exerzieren muss, damit ich früh erkenne welche Schritte wie gelöst werden können, damit kein stupides "if not then else" Monster entsteht, das mehr Zeit für maintenance verschlingt als intelligente Entscheidungshilfen zu liefern Denn ich sehe darin ein sehr kompliziertes Problem einer Maschine einen Daten-Input und eine Rechenvorschrift zu übergeben und die Anwendung so allgemein zuhalten, wie "Machmal für alle Daten Algo-FX3000 aber entscheide bitte schön selbst welche Daten aus dem ganzen Wortgulasch für FX-3000 in Frage kommen und spucke nur die Ergebnisse aus die sinnvoll sind". Nun zum Teil was bisher konkret ist: 1) Es geht darum in R Objekte abzubilden die in einer XML definiert sind.
2) Anhand dieser Objekte sollen Daten aus einem DBS gelesen werden, dazu bedarf es mEn für jedes DBS wieder einen individuellen Connector (Dahin gehend gibt es schon ansätze wie RJDBC). Nun ist dieser Ansatz, dass diese XML solche refkeys enthalten soll, aus der Kommunikation (das soll nicht heißen das ich wirklich verstanden habe was eigentlich kommuniziert werden sollte) mit einem Software-Entwickler entstanden. Dabei ist auch der Begriff DTD gefallen was ich noch nicht kannte, aber dies scheint ein Standard wie XSD zu sein. Ich kenne mich leider nicht so gut aus wie der Entwickler, für mich ist nur soviel rübergekommen, dass dieser vermutlich Konzept-Bilder wie JAXB und DBAL-doctrine vor Augen hat in denen er vermutlich zuhause ist, ohne das er ausgesprochen hat. Diese Konzepte konnte ich in R bisher so nicht wiederfinden. Wie auch immer, ich vermute das anhand einer DTD die man dem XML Parser zum lesen gibt, dieser dann wissen soll, wie er mit key und refkey zu handtieren hat.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Hui, da hast Du Dir ja Mühe gegeben - leider habe ich immer noch nicht kapiert, wieso am XML selber etwas manipuliert werden soll! Wenn Du die XML-Struktur selbst definierst, dann mache es doch von vornherein so, dass die Struktur passt! XML zu transformieren, um danach etwas damit zu tun, ist eigentlicn nur dann sinnvoll, wenn man auf die Eingabe keinen Einfluss hat *und* die Weiterverarbeitung ein bestimmtes XML-Format voraussetzt. Wenn Du aber eh ein Programm schreibst, welches das Eingabe-XMl lesen und daraus abgeleitet handeln soll, überführe die Informationen aus dem XML in eine *interne* Datenstruktur. Irgend wie fehlt mir hier noch der genaue Ansatzpunkt, wieso die *Struktur* des XML manipuliert werden soll...
|
Öttinger
(Themenstarter)
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Hui, da hast Du Dir ja Mühe gegeben - leider habe ich immer noch nicht kapiert, wieso am XML selber etwas manipuliert werden soll!
Blöd dann war das für umsonst. Ich möchte das XML Dokument eigentlich nicht manipulieren, sondern wissen, ob ich das richtig sehe, dass man einem XML-Parser mit so einer DTD beibringen kann wie er die refkeys zulesen hat. D.h. das die XML Struktur auf die referenziert wird in eine interne Struktur überführt wird. Kann aber auch sein das ich die Anwendung mit den keys falsch deute, wobei ich mir keinen anderen Nutzen vorstellen kann als diesen, dass eben beim Einlesen der XML diese Ersetzung vom XML-Parser als Funktionssprektrum dem Programmierer zur Verfügung gestellt wird.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Äh... nö! Eine DTD ist - analog zu XML Schema oder Realx - einfach eine Beschreibung der *Struktur* eines XML-Dokuments. Sie liegt fest, *welche* Elemente vorkommen können, in welcher Reihenfolge oder Alternative diese vorkommen, welche Werte innherhalb der Tags stehen dürfen usw. DTDs sind mir jedoch seit über 10 Jahren nicht mehr über den Weg gelaufen; XML-Schema hat diese so ziemlich verdrängt; zu Recht (Ok, Relax fand ich auch ganz spannend!). Mit einer solchen Schema-Datei kann ein XML-Parser nicht nur überprüfen, ob das Dokument überhaupt valides XML ist, sondern ob es auch gegenüber der Schemadefinition valide ist. Das hat aber noch *nichts* mit internen Strukturen und Zusammenhängen zu tun; dies muss innerhalb eines Programmes aus der XML-Struktur abgeleitet werden. Wenn ich Dein Beispiel von oben richtig verstehe, hast Du Elemente und Teile, die aus Elementen bestehen. Also wie bei Lego-Steinen und Lego-Modellen, die aus Steinen bestehen. Im XML sind die Elemente beschrieben und welche Elemente zu einem Teil gehören. Intern musst Du das halt einfach in passende Datenstrukturen "pressen".
|
Öttinger
(Themenstarter)
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Ich glaube ich habe mich falsch ausgedrückt mir geht es nicht darum welches Schema zur Validierung einer XML verwendet wird, und es soll auch der XML Parser nicht wissen wie er die Daten in eine Internestruktur überführen kann, sondern der Parser soll lediglich wissen das zum Element mit refkey="a" das XML Element mit dem key="a" gehört, sofern sie mit dem gleichen XML Tag definiert wurden, solch ein Funktionsumfang eines Parsers wäre natürlich schön, Gestz dem Falle das soetwas eine geläufige Methode ist. Das ih diesen Funktionsumfang mit DTD und XSD in Verbindung gebracht habe war nur eine Vermutung, das anhand dieser der XML-Parser sich die Referenzen abzuleiten weiß.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Öttinger schrieb: ... sondern der Parser soll lediglich wissen das zum Element mit refkey="a" das XML Element mit dem key="a" gehört, sofern sie mit dem gleichen XML Tag definiert wurden
Und was genau bringt das? Das wird doch erst relevant, *wenn* ich mir aus dem XML eine Programm interne Struktur aufbaue! Meines Wissens kann so etwas kein XML-Parser; zumindest wäre mir noch keiner über den Weg gelaufen! (Was genau soll der Parser denn auch damit "machen", wenn er auf eine solche Referenz stößt?) Ein XML-Parser kann lediglich die Struktur in einem interne XML-Repräsentation (meist eine Baum-Struktur) wandeln und auf Validität prüfen; mittels eines Schemas auch auf Validität hinsichtlich des Aufbaus, also durchaus Domänen speziell. Aber Logiken prüfen kann er nicht! Also z.B. wenn PLZ '12345' lautet, dann muss als Ort auch 'Entenhausen' im Dokument stehen. Er kann auch keine Struktur verändern - was Dir vorschwebt. Ich habe mal in Python (3.x) ein Beispiel gebaut, welcher so einen Parsing-Prozess in eine interne Datenstruktur verdeutlicht: Gist Ich habe mir mal eine simple Domänenklasse Element definiert, die ein Element in meinem Programm darstellen kann. In der Parsing-Funktion get_elements baue ich mir ein Mapping vom Schlüssel auf ein solches Element-Objekt auf. Damit habe ich alle Elemente aus der XML-Datei in einer internen Repräsentation vorliegen. Also z.B.:
"a" -> Element("a", "abc")
"b" -> Element("b", "def")
usw. Anschließend kann ich nun die Teile (Parts) einlesen. Ich habe das Beispiel mal aufgebohrt, damit die Wiederverwendbarkeit der einzelnen Elemente deutlich wird und mehrere Parts definiert. Ein Part wird bei mir durch eine einfache Liste dargestellt; alle Parts sind dann in einem Dictionary aus dem Namen eines Parts und einer Liste von Elementen beherbergt. Als Ausgabe erhalte ich das hier:
Habe 2 Parts gefunden
Part 'komplexes Teil':
- Element a: abc
- Element b: def
- Element c: ghi
Part 'simples Teil':
- Element b: def
- Element c: ghi
Wie man sieht, kommen die Elemente b und c in zwei verschiedenen Parts vor - intern sind das aber identische Element-Objekte. Genau das ist doch der Vorteil von solchen Referenzen im XML; ich brauche eben nicht unterhalb eines <part>-Elements die Definition eines <element>-Elements doppelt und dreifahc zu schreiben, sondern kann das in eine separate Definition auslagern. Nebenbei wäre es auch in einer Datenstruktur Quatsch, mehrfach vorkommende Dinge mehrfach im Speicher zu halten. Das Mapping eines refkey -Schlüssels auf die internen Elemente ist Domänen-Wissen und damit Teil des Parsing-Prozesses, der *auf* dem XML-Parser aufsetzt. Ich habe leider immer noch nicht verstanden, *was* genau durch dieses gewünschte Parser-Verhalten gelöst werden soll!
|
Öttinger
(Themenstarter)
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Ich habe leider immer noch nicht verstanden, *was* genau durch dieses gewünschte Parser-Verhalten gelöst werden soll!
Genau das was du im folgenden beschreibst, wobei wenn man es zeilenweise betrachtet dies speichertechnisch nur sinn macht wenn das Element selbst nicht nur aus <elem .../> besteht. Genau das ist doch der Vorteil von solchen Referenzen im XML; ich brauche eben nicht unterhalb eines <part>-Elements die Definition eines <element>-Elements doppelt und dreifahc zu schreiben, sondern kann das in eine separate Definition auslagern. Nebenbei wäre es auch in einer Datenstruktur Quatsch, mehrfach vorkommende Dinge mehrfach im Speicher zu halten.
Das Mapping eines refkey-Schlüssels auf die internen Elemente ist Domänen-Wissen und damit Teil des Parsing-Prozesses, der *auf* dem XML-Parser aufsetzt.
Genau das trifft meine Frage, ob dieses Mapping in gägngigen Programmiersprachen bereitgestelt wird, denn es scheint ja ein immer wiederkehrender Prozess zu sein. Und ich dachte wenn der Parser schon eine Meta Sprache wie XSD kann dann kann man dem auch sowas beibringen, ohne das selbst zu formulieren bzw. programmieren.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Öttinger schrieb: Genau das trifft meine Frage, ob dieses Mapping in gägngigen Programmiersprachen bereitgestelt wird, denn es scheint ja ein immer wiederkehrender Prozess zu sein.
Äh... also jede halbwegs benutzbare Sprache sollte einen Mapping-Mechanismus kennen. Solch eine Datenstruktur ist einer der Building-Blocks der Informatik 😉
Und ich dachte wenn der Parser schon eine Meta Sprache wie XSD kann dann kann man dem auch sowas beibringen, ohne das selbst zu formulieren bzw. programmieren.
Du hast glaube ich immer noch nicht verstanden, was ein XML-Parser macht bzw. wozu er gut ist! Der Parser überführt das *serialisierte* XML, also das, was wirklich als String mit Tags in einer Datei liegt, in einen abstrakten Syntax Baum, also eine *interne* Abbildung der Struktur im Speicher. Aus dieser Struktur Domänen-Objekte zu erstellen ist *nicht* Teil des XML-Parsers, sondern immer Teil Deiner Domänen-Logik.
|
Öttinger
(Themenstarter)
Anmeldungsdatum: 28. Januar 2009
Beiträge: 504
|
Äh... also jede halbwegs benutzbare Sprache sollte einen Mapping-Mechanismus kennen. Solch eine Datenstruktur ist einer der Building-Blocks der Informatik 😉
Äh kapier ich nicht, welche Funktion übernimmt das in deinem Bsp.? Du hast das ja selbst ausgeschrieben, also scheint es diesen Mapping Mechanismus nicht zugeben. Falls du das generell meinst, dann war das nicht Frage, dann muss ich mich wohl beim nächsten mal präziser ausdrücken, tut mir leid.
Du hast glaube ich immer noch nicht verstanden, was ein XML-Parser macht bzw. wozu er gut ist! Der Parser überführt das *serialisierte* XML, also das, was wirklich als String mit Tags in einer Datei liegt, in einen abstrakten Syntax Baum, also eine *interne* Abbildung der Struktur im Speicher. Aus dieser Struktur Domänen-Objekte zu erstellen ist *nicht* Teil des XML-Parsers, sondern immer Teil Deiner Domänen-Logik.
Achso das habe ich leider nicht kommen sehen, dass ich das nicht verstehe. Ich wollte einfach nur wissen ob irgend ein Zeugs mir die Funktion bereitstellt getRefObjekt(XML.NODE* node) so wie der Parser bereits die Funktion XMLTreeParse oder ähnliches bereitstellt, das war alles. Das wäre ja kein Beinbruch wenn es sowas schon gäbe, mehr wollte ich vorerst nicht wissen. Danke für die Lehrstunden und Zeit habe ich jetzt nicht gespart.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Öttinger schrieb: Äh kapier ich nicht, welche Funktion übernimmt das in deinem Bsp.?
Zeile 43! Ich hatte darüber auch nen Kommentar geschrieben 😉
Du hast das ja selbst ausgeschrieben, also scheint es diesen Mapping Mechanismus nicht zugeben. Falls du das generell meinst, dann war das nicht Frage, dann muss ich mich wohl beim nächsten mal präziser ausdrücken, tut mir leid.
Das kapiere ich jetzt wiederum nicht! Ein "Mapping" ist einfach eine gängige Datenstruktur, die es in den meisten Programmiersprachen out of the box gibt (sprich, man muss sich das nicht selber als Datentypen erst erstellen). So eine Struktur brauchst Du zur Lösung dieses Problems, damit Du beim Parsen der XML-Struktur (also dem Prozess, der *auf* dem Resultat des XML-Parsers aufsetzt) bei den Knoten mit dem refkey -Attribut einfach auf die *zuvor* in eine Datenstruktur eingelesenen Element -Objekte zugreifen kannst. Das passiert eben in Zeile 43.
Ich wollte einfach nur wissen ob irgend ein Zeugs mir die Funktion bereitstellt getRefObjekt(XML.NODE* node) so wie der Parser bereits die Funktion XMLTreeParse oder ähnliches bereitstellt, das war alles.
Was sollte diese hypotetische Funktion denn als Datentypen zurückliefern? Ein "Node"-Objekt? Was wäre damit großartig gewonnen?
Danke für die Lehrstunden und Zeit habe ich jetzt nicht gespart.
Ich kapiere wirklich nicht, wieso Du hier so zynisch wirst - ehrlich gesagt habe ich mir ziemlich viel Mühe bei der Beantwortung Deiner Fragen genommen bzw. der Ergründung, worum es Dir eigentlich geht. Ich glaube nur nach wie vor, dass Dir noch nicht bewusst ist, dass man meist nicht auf XML-Strukturen arbeiten will, sondern die Informationen einer solchen XML-Struktur in seine Domänen-Repräsentation überführen will, da man in *dieser* das eigentliche Business-Problem löst. Vielleicht noch mal als greifbares Beispiel:
MS Office verwendet zum Speichern (= Serialisieren / Persistenz) XML, genauso wie Libre / OpenOffice. Wenn Du in Word die Überschriften der "Ebene 1" nun umformatierst, so wird intern eben *nicht* der Knoten aus dem zugehörigen XML gesucht und dort die neue Formatierung eingetragen, sondern es wird irgend ein Domänenobjekt geben, welches diese Überschriftenschablone repräsentiert und *dort* wird irgend ein Attribut gesetzt. Das XML wird lediglich beim Speichern und Laden verwendet, um von bwz. in die Domänenstruktur zu gelangen. Auf blanken XML-Knoten arbeitet Word da (sicher) nicht. So wie ich das Problem von Dir weiter oben verstanden habe, sind in dem XML Regeln für die Verarbeitung von Daten zu finden. Diese Regeln müssen in der Software ja irgend wie repräsentiert sein. Die Herausforderung ist es nun, aus der XML-Struktur, die Dir ein XML-Parser liefert, diese Repräsentationen zu erstellen. Dazu gehört es eben, Dinge wie "Verweise" aufzulösen (Zeile 43 😉 ), Daten in Objekte zu packen (get_elements , get_parts ) usw. Das *kann* Dir einfach kein Parser abnehmen, das *ist* ein Parsing auf höherer Ebene. Da hilft auch kein Sarkasmus - ich bin nicht schuld daran, dass es das, was Du vermeindlich suchst, nicht gibt. Ich habe Dir lediglich versucht klar zu machen, *wieso* es das nicht gibt und *dass* Du eigentlich ein ganz anderes Problem lösen willst 😉
|