# XML-Datum als Referenz auf Objekt-Variable auslesen



## martingallee (14. Sep 2008)

Liebe Java-und-XML-Experten,

ich schreibe wegen eines Problems, an dem ich mir jetzt schon seit ein paar Wochen die Fingernägel kurz tippe, bei dem ich aber einfach nicht weiter komme. Möglicherweise kann mir ja jemand einen Tipp oder Fingerzeig geben, in welche Richtung ich suchen muss.

Mein Programm soll eine Reihe von Objekten (der Klasse "Beitrag.java") instantiieren, die alle mehrere Instanzvariablen enthalten sowie eine Funktion, die auf der Basis bestimmter Bedinungen diese Instanzvariablen manipuliert. Eine (SAX-)Parserklasse geht zu Beginn ein XML-Dokument durch und instantiiert die jeweiligen "Beitrag"-Objekte mit den dort vorgefundenen Werten. Da, wie gesagt, eine Methode der Klasse "Beitrag.java" auf der Basis von Bedingungen operiert, werden die aus dem XML-Dokument eingelesenen Werte in den "Beitrag"-Objekten in mehreren HashMaps gespeichert, die von den Funktionen dann abgearbeitet werden. - So weit, so gut.

Das Problem ist nun aber Folgendes: Da sich die Bedingungen, auf denen die Methode der "Beitrag"-Objekte fußt, zum Teil auf dem Zustand von Objektvariablen *anderer Klassen* bezieht, die vor und unabhängig von den "Beitrag"-Objekten bestehen, stehen in der XML-Datei eben Referenzen auf diese anderen Objekte und ihre Instanzvariablen, zum Beispiel "andereKlasse.einIntegerWert". Wenn ich diese mit dem Parser aber auslese und in die HashMap eines "Beitrag"-Objekts schreibe, versteht er den Ausdruck von gerade nicht als Referenz auf eine Objektvariable, sondern als *String*. Und wenn die Methode eines "Beitrag"-Objekts dann an dieser Stelle in der HashMap vorbeikommt, enthält diese nicht etwa den *Wert* der *Variable* andereKlasse.einIntegerWert, sondern vielmehr den Ausdruck *andereKlasse.einIntegerWert* SELBST - also etwas ganz Anderes, eben weil er das, was er aus dem XML-Dokument ausliest, als String versteht. Das tut er selbst dann, wenn ich den String, bevor ich ihn in die HashMap schreibe, ausdrücklich nach (Object) caste. (Wenn ich den selben Ausdruck "andereKlasse.einIntegerWert" dagegen direkt in die HashMap schreibe, ist das gar kein Problem, das wird als Referenz auf die Objektvariable interpretiert.)

Meine Frage ist also konkret folgende: Wie schaffe ich es im Rahmen des beschriebenen Szenarios, dass ein aus einem XML-Dokument ausgelesener Wert als *Variablenname* und insofern als *Referenz* auf einen *anderen* Wert verstanden wird, und nicht einfach als String? Ich hoffe, die Frage ist halbwegs verständlich, ich habe es trotz ausführlicher Suche bisher noch nicht einmal zu einem Stichwort geschafft, unter dem ich bezüglich dieses Problems sinnvoll suchen könnte. Ich bin daher für jede Hilfe dankbar - und bis hierhin auf jeden Fall schon mal für die Aufmerksamkeit.

Mit freundlichen Grüßen aus Stuttgart,

Martin


----------



## foobar (14. Sep 2008)

Warum nutzt du nicht eine DOM-Api oder am besten JAXB oder EMF? Das ist wesentlich einfacher als sich mit SAX rum zu ärgern.
DOM hat auch den Vorteil, daß du auf andere Elemente im Baum zugreifen kannst und nicht erst warten mußt bis das anderere Element gelesen wurde.


----------



## martingallee (18. Sep 2008)

Hallo foobar,

vielen Dank für Deine Antwort. Wenn ich das richtig verstanden habe, wird durch XML-Binding aus den 
einzelnen XML-Elementen ein Objekt mit entsprechenden Instanzvariablen erzeugt. Mein Problem ist aber 
Folgendes: Ich habe mehrere Objekte einer Klasse (nennen wir sie "FrontEnd.java"), deren Ausgabe vom Zustand der Elemente von Objekten einer anderen Klassen ("BackEnd.java") abhängt, wobei sich letztere *zur Laufzeit* ändern können (das hätte ich womöglich in meiner ursprünglichen Frage deutlicher machen müssen - sorry). 

Da es sich um eine Vielzahl von "FrontEnd"-Objekten handelt, die auch jeweils andere Variablen von "BackEnd.java" überprüfen, ist nun das Problem, dass, wenn ich eine XML-Datei mit den entsprechenden Daten parse und daraus "FrontEnd"-Objekte instantiiere, diese Daten zum Teil auf Elemente von "BackEnd.java" verweisen, und zwar als Referenz, weil sich diese Werte, wie gesagt, zur Laufzeit ändern.


```
Class BackEnd
{

  //

  int checkMeFirst;
  int checkMeSecond;
  int checkMeThird;
  etc.

}
```

Die XML-Datei für drei "FrontEnd"-Objekte würde also - vereinfacht - so aussehen.


```
<frontend>
<check>backEnd.checkMeFirst</check>
</frontend>

<frontend>
<check>backEnd.checkMeSecond</check>
</frontend>

<frontend>
<check>backEnd.checkMeThird</check>
</frontend>
```

Daraus macht meine SAX-Parser-Klasse nun drei "FrontEnd"-Objekte, die alle jeweils eine andere Elementvariable eines "BackEnd"-Objekts überwachen. Die Frage ist nun aber, wie ich diese XML-Daten so in ein "FrontEnd"-Objekt überführe, dass dieses zum Beispiel backEnd.checkMeFirst als *Referenz* auf den jeweiligen Wert eines "BackEnd"-Objekts enthält und entsprechend reagieren kann. 

Ich habe es zunächst mit einer HashMap als Element von "FrontEnd" versucht und dann zum Beispiel backEnd.checkMeFirst als Object hineingeschrieben. Das Problem ist nur, dass das dann eben nicht als Referenz auf backEnd.checkMeFirst gelesen wird, sondern als *String* "backEnd.checkMeFirst". Momentan versuche
ich es mit dem ScriptEngine, der es seit Java 6 erlaubt, JavaScript auszuführen. Dessen "eval()"-Methode sah zwar
am Anfang recht vielversprechend aus, aber auch hier hängt das Ganze daran, dass ich zwar in eine Elementvariable von "FrontEnd" den Wert "backEnd.checkMeFirst" schreiben kann - auf den WERT von backEnd.checkMeFirst kann ich aber eben nicht zugreifen.

Ich hoffe, mein Problem ist zumindest etwas deutlicher geworden.

Viele Grüße,

Martin[/code]


----------



## foobar (18. Sep 2008)

Ok, ich verstehe so ungefähr was du machen willst.

Entweder du untersuchst vor der Serialisierung deine Objekte mit der ReflectionAPI und persistierst das ganze dann mit einer DOM-Api. Oder du überlegst dir ein Sinnvolles Model, daß dann auch mit JAXB serialisiert werden kann.
Was ist denn der Sinn des ganzen?


----------



## martingallee (18. Sep 2008)

Hallo foobar,

danke für Deine Hinweise, da werde ich mich wohl mal in die ReflectionAPI einlesen müssen. Alternativ dazu 
werde ich mir auch mal ansehen, ob und welche ScriptEngines ohne Probleme für PHP benutzt werden können,
denn mit der $$-Funktion von PHP kann man ja auch auf den Wert eines String-Inhalts zugreifen, der dann als
Name einer Variable interpretiert wird.

So, wie Du die letzte Frage gestellt hast, habe ich etwas schmunzeln müssen, denn ich komme aus der Philosophie
Das Programm soll mal eine CD-ROM-Beilage für ein Buch werden, die mit "Der Autor im Gespräch" betitelt ist.
Man kann sich dann auch Multiple-Choice-Basis mit dem Autor (also mir) über den Inhalt des Buches unterhalten.
Mein "KI"-Modell sieht dabei vor, dass (vor allem auf der Basis der vom Leser ausgewählten Gesprächsbeiträge) so
eine Art philosophisches Profil ("Profil.java") von ihm erstellt wird, das feste Eigenschaften (etwa den Namen) aber auch änderbare Eigenschaften (zum Beispiel: äußert sich jemand eher in Richtung der griechischen oder der modernen Philosophie?) enthält. Bevor sich das Programm äußert, schaut es erst in diesem Profil nach, ob die Äußerung entsprechend modifiziert werden kann. Alle Beiträge sind dabei Objekte der Klasse "Beitrag.java" und enthalten jeweils einen Basistext, zum Beispiel ganz am Anfang "Guten Tag". *Dieses* Beitrag-Objekt würde dann in Deinem Profil nachsehen, dort die String-Variable "name" auslesen, und den Ursprungstext zu "Guten Tag, foobar" ergänzen. Das ist aber natürlich  nur der sehr simple Anfang, wenn das Gespräch weiter fortgeschritten ist (also andere Beitrag-Objekte angezeigt  werden), könnte der Basistext auch "Hegel widerspricht Kant nun deutlich in seiner Erkenntnistheorie" lauten, der dann nach dem selben Prinzip zu "Hegel widerspricht Kant nun deutlich in seiner Erkenntnistheorie - aber das wussten Sie bestimmt schon vorher, Sie hatten sich ja vorhin mehrfach zu Hegel geäußert" ergänzt werden, wobei *dieses* Beitrag-Objekt natürlich in Deinem Profil ganz andere Sachen nachsieht als das vorher, das Dich begrüßt hat. Ich hoffe, das Prinzip wird halbweg deutlich. - Und das ist nun eben der Grund dafür, dass die Beitrag-Objekte zur Laufzeit jeweils unterschiedliche Elementvariablen des "Profil"-Objekts auslesen können müssen, denn ob Du zum Beispiel eher einer philosophischen Schule zuneigst oder einer anderen kann sich natürlich im Verlauf des Gesprächs ändern. Das "Profil"-Objekt (von dem es ja nur eines geben muss) sähe also etwa so aus:


```
Class Profil
{

  //

  String name;
  int hegelGelesen; // 0 - nein, 1 - ja
  int eherAntikeoderModern; // 0 bis 100, je höher, desto moderner
  etc.

}
```

Die Beitrag-Objekte haben jeweils einen Ausgangstext sowie eine Funktion, die diesen auf der Basis der Werte der für *dieses* Beitrag-Objekt relevanten Elementvariablen von "Profil" modifiziert. Dazu hat jedes Beitrag-Objekt eine Funktion, die den Ausgangstext auf der Basis der für *dieses* Beitrag-Objekt relevanten Werte des Profils modifiziert.


```
Class Beitrag
{

  //
  
  String ausgangsText; // Hier zum Beispiel "Guten Tag,"

  HashMap map; // Hier zum Beispiel ("1", "profil.name")

  String modify()
  {

     // 

     Hier wird nun die jeweilige HashMap durchsucht und je nach Wert der ausgelesenen Werte von "Profil" der 
     Ausgangstext ergänzt und zurückgegeben - also hier zum Beispiel "Guten Tag, foobar".

   }

}
```

Wenn ich in die HashMap den Ausdruck profil.name eintrage, wird das problemlos als int-Variable erkannt, wenn
ich den selben Ausdruck aber als String aus der XML-Datei auslese und die HashMap damit erzeuge, versteht der Computer an dieser Stelle eben immer ein String.

Ich hoffe, ich habe Dich mit dem Philo-Kram nicht allzu sehr zugeblubbert.

Nochmals vielen Dank,

Martin


----------



## martingallee (18. Sep 2008)

Hallo foobar,

dank Deines Tipps funktioniert das Ganze jetzt mit der ReflectionAPI. Der Unterschied (und Vorteil) zu meinem
Vorgehen ist, dass die "getField"-Methode einen String erwartet - und genau den bekommt sie auch, wenn ich
ein XML-Dokument parse. Dort hinein schreibe ich also nur die Namen der Instanzvariablen, die ich anschließend 
der "getField"-Methode übergebe.

Nochmals vielen Dank,

Gruß Martin


----------

