# XML Parsen - IDs auslesen - HTML generieren



## =_=_= (25. Mai 2009)

Hi Leute,

bin neu und wende mich mit meinem Problem an Euch, nachdem ich seit knapp einer Woche auf der Stelle trete. Ich realisiere ein firmeninternes Projekt mit Java/Struts/Hibernate. 

Original Sourcecode darf ich natürlich nicht posten, da es Eigentum der Firma ist, auch wenn ich der einzige Entwickler bin und es quasi "mein" Projekt ist. Ich hoffe dafür habt Ihr Verständnis. 


Aber das Problem lässt sich auch so gut darstellen.

Folgender Sachverhalt:

Ich habe ein HTML Formular. Dieses ist zu Beginn leer und mittels JavaScript habe ich mir ein paar Funktionen geschrieben, mit denen ich dynamische Eingabefelder generiere (also ganz simple <input> HTML Elemente). 

Das Ganze funktioniert in einer zweistufigen Hierarchie. Das heisst: Man kann Elternelemente generieren und zu jedem Elternelement auch beliebig viele Kinderelemente. Das Ganze habe ich mit JavaScript über den DOM Baum realisiert und es funktioniert problemlos. 

Nun werden die Eingaben in den generierten <input> Feldern mittels Struts an meine Java Programmlogik übergeben. Die Werte stehen bei der Übergabe in einer HashMap in der Form:


```
HashMap<String, String[]>
```

Mittels Iterator über das daraus resultierende "keySet" ziehe ich mir die Schlüssel raus und sortiere diese. 

An diesem Punkt wirds viell. ein wenig umständlich für Manchen Leser, aber ich habe die nächsten Schritte so realisiert, weil es für mich verständlicher war und ich gerne eine "eigene" Lösung dafür finden wollte. 

Also die Schlüssel werden von meiner eigens geschriebenen Klasse sortiert und zwar so, dass ich erstmal die ID, die ich von meinem HTML <input> Element erhalte, parsen muss, da es sich um einen String handelt. Die ID der Elemente sieht folgendermaßen aus:


```
Integer-Wert | Sonderzeichen als Seperator | Integer-Wert
```

Der erste Int-Wert gehört immer zum Elternelement, der zweite Int-Wert zum Kindelement.

Einfaches Beispiel:

Elternelement 1 hat die ID: 
	
	
	
	





```
1?
```

Kindelement 1 hat die ID: 
	
	
	
	





```
1?1
```

Kindelement 2 hat die ID: 
	
	
	
	





```
1?2
```

usw....

Ich hoffe es ist verständlich was ich meine.

Gut, nach dem Parsen der ID baue ich mir daraus eine Liste, die wiederum Listen enthält, und zwar sortiert nach den IDs.

Das sieht als Pseudocode so aus:


```
[ [1?, 1?1, 1?2] [2?, 2?1, 2?2] [3?, 3?1] ]
```

Das hat den Hintergrund, dass ich meine IDs besser verarbeiten kann, wenn jede zusammenhängende ID-Gruppe in einer eigenen Liste steht. 

Aus diesen Listen baue ich mir nun mittels "*JDOM*" ein XML Dokument welches dann letzten Endes als 
	
	
	
	





```
byte[]
```
 (byte-Array) in ein BLOB Feld in meiner Datenbank gesschrieben wird.

So, langsam wird der Text echt lang, also kürze ich es jetzt ein wenig und komme zum direkten Problem, welches auf all dem aufbaut:

Ich möchte das Ganze nun rückwärts machen, also aus dem BLOB Feld der DB mein XML Dokument lesen, parsen und daraus dann wieder HTML Elemente generieren. 

Wozu? Nun ja, Weil das der notwendige Schritt ist, wenn ein Anwender in meiner WebApp etwas editieren möchte. Dann müssen bereits angelegte DB-Objekte mit zuvor gespeicherten Werten diese Werte auch wieder zum Editieren in die selben <input> Felder schreiben.

Mein Problem, an dem ich momentan stehe:

WIE genau übergebe ich meine ausgelesenen Werte an Struts? Und wie genau generiere ich meine <input>-Felder um sie mit den übergebenen Werten zu füllen? 

Die ausgelesenen Werte verarbeite ich im Moment per "SAXBuilder" was auch gut klappt nur eben der Sprung hin zur Übergabe an Struts will nicht klappen... 

Ich hoffe mir kann jemand ein wenig auf die Sprünge helfen!! 

Falls das jetzt alles zu viel Overkill war  dann poste ich morgen gerne mal etwas Sourcecode. 


Gruss

=_=_=


----------



## gex (26. Mai 2009)

Wenn ich dich richtig verstehe arbeitest du sehr Client-orientiert, spricht mit JavaScript Inputs in den DOM stellen, und dann Daten eingeben und erst wenn dieser Schritt abgeschlossen ist, gibt es einen Request (GET/POST) an den Server, wo dann die Daten manuell aus dem Request gezogen werden?!

Wie die meisten Frameworks will ja auch Struts das manuelle arbeiten mit Request / Response so weit wie möglich erübrigen.

Was du mit Übergabe an Struts meinst, ist mir indes nicht ganz klar. Prinzipiell kannst du dir ja in der Struts action die Daten aus der DB holen und in irgend ein Objekt verpacken, dieses dann in den request-scope stecken, danach an ein JSP dispatchen und dort mit Tags (JSTL, Struts nested Tags oder welche auch immer) oder gar Scriptlets (obwohl mittlerweile eher verpönnt) reines HTML generieren lassen, welche keine Felder hat, die direkt mit einem Struts ActionForm gemappt sind.

Ein evtl. einfacherer Ansatz wäre es, anstelle des clientseitigen erstellen der Felder serverseitig die Hierarchie als Objekt zu halten, welches dann auch erweitert werden kann, jedoch immer wie request. Den Objektbaum baust du dann am besten mit dem Composite Pattern und versiehst es geschickt mit JAXB Annotations, dann sollte sowohl das marshalling wie auch das unmarshalling geschenkt sein (kein Code-Overhead), und wenn due dann mit den Struts eigenen Tags die Textfields aufbereitest spielt es keine Rolle ob du auf einem neuen oder bereits gespeicherten Objektbaum arbeitest.


----------



## =_=_= (26. Mai 2009)

> Wenn ich dich richtig verstehe arbeitest du sehr Client-orientiert, spricht mit JavaScript Inputs in den DOM stellen, und dann Daten eingeben und erst wenn dieser Schritt abgeschlossen ist, gibt es einen Request (GET/POST) an den Server, wo dann die Daten manuell aus dem Request gezogen werden?!



Ja genau, so habe ich das gemeint.




> Was du mit Übergabe an Struts meinst, ist mir indes nicht ganz klar.




Also um es mal in Codeform zu verdeutlichen:

Ich baue mir mit JavaScript folgendes Konstrukt für ein <input>-Element:


```
inputParentElement.setAttribute("name", "elementProperties['" + inputParentElementCounter + "?']");
```

Das bedeutet, dass meine Übergabe mittels Struts ja so abläuft, dass der Wert des <input>-Feldes in meine HashMap geschrieben wird, welche in meiner Java Klasse erstellt wird:


```
private Map<String, String[]> elementProperties = new HashMap<String, String[]>();
```

Über diese HashMap iteriere ich mit einem Iterator, der aus dem 


```
elementProperties.keySet()
```

gebaut wird und greife dann so auf meine Elemente zu. 


Das war nun gemeint mit der Übergabe an Struts, na ja, viell. etwas unglücklich formuliert, aber es ist damit die Schnittstelle zwischen HTML-Formular und Java Klasse gemeint.



Das hier:



> Ein evtl. einfacherer Ansatz wäre es, anstelle des clientseitigen erstellen der Felder serverseitig die Hierarchie als Objekt zu halten, welches dann auch erweitert werden kann, jedoch immer wie request. Den Objektbaum baust du dann am besten mit dem Composite Pattern und versiehst es geschickt mit JAXB Annotations, dann sollte sowohl das marshalling wie auch das unmarshalling geschenkt sein (kein Code-Overhead), und wenn due dann mit den Struts eigenen Tags die Textfields aufbereitest spielt es keine Rolle ob du auf einem neuen oder bereits gespeicherten Objektbaum arbeitest.



...habe ich nicht komplett verstanden, aber ich kann meine Herangehensweise jetzt auch nicht mehr ändern, dafür ist schon zu viel Code geschrieben worden.

Aber dennoch, Danke für die Idee.... 


Gruss


----------



## gex (27. Mai 2009)

Also konkret ist das Problem, dass du das gespeicherte XML wieder in Input Felder umwandeln kannst, richtig?

Eigentlich 2 Punkte die aus meiner Sicht wichtig sind:
1. Die Reihenfolge der InputFelder muss wieder dem entsprechen, was gespeichert wurde - oder?
2. Das XML ist wohl hierarchisch, auf dem GUI jedoch flach

Den ersten Punkt müsstes du so lösen, dass du eine Collection verwendest, die eine bestimme Reihenfolge sicherstellt,
List oder falls es eine Map sein soll die LinkedHashMap... Diese Collection füllst du dann durch deinen SAXBuilder (beim iterieren). Beim füllen dieser Collection daran denken, dass sie in einer Form vorliegen muss, wo du dann einfach in der
JSP darüber iterieren kannst, um wieder n-Elemente mit der entsprechenden ID generieren kannst, die sich dann
so Verhalten, wie neue angelegte.

Durch deinen "Approach" hast du dir halt ein bisschen viel manuelle Arbeit eingehandelt.

Setzt dir mal die verschiedenen, logischen Schritte auf, welche gegeben sein müssen und versuche erst nachher diese umzusetzen. Wenn du sie in Teilschritte aufteilst, dann kristallisiert sich vielleicht besser heraus, wo genau du noch Hilfe benötigen solltest.


----------



## =_=_= (27. Mai 2009)

```
Also konkret ist das Problem, dass du das gespeicherte XML wieder in Input Felder umwandeln kannst, richtig?
```

Exakt! 



```
Die Reihenfolge der InputFelder muss wieder dem entsprechen, was gespeichert wurde - oder?
```

Ebenfalls richtig.



```
Das XML ist wohl hierarchisch, auf dem GUI jedoch flach
```

Das XML ist hierarschisch, ja. Das geht in meinem Fall aus der Vorsortierung meiner Elemente hervor.

Was mit 





> GUI jedoch flach


 gemeint ist verstehe ich nicth ganz.




> Den ersten Punkt müsstes du so lösen, dass du eine Collection verwendest, die eine bestimme Reihenfolge sicherstellt,
> List oder falls es eine Map sein soll die LinkedHashMap... Diese Collection füllst du dann durch deinen SAXBuilder (beim iterieren).




Habe ich getan, eine Liste gebaut mit allen Elementen in der Reihenfolge, wie sie ausgelesen werden sollen für meine JSP. 




> Beim füllen dieser Collection daran denken, dass sie in einer Form vorliegen muss, wo du dann einfach* in der
> JSP darüber iterieren kannst, um wieder n-Elemente mit der entsprechenden ID generieren kannst*, die sich dann
> so Verhalten, wie neue angelegte.




Hier stockt es nun gerade bei mir. Wie komme ich aus meiner JSP an die Inhalte meiner Liste um daraus HTML <input> Felder zu genereieren? Ich google mit grade nen Wolf und komme auf keine klare Lösung... ???:L


Aber Danke, Dein Posting hat mir schon deutlich weiter geholfen! 

Gruss


----------



## gex (27. Mai 2009)

Welche Struts Version verwendest du?

Also deine List kannst du ja als Attribut in die Session speichern.

```
request.setAttribute("meinKey", meineList);
```

In deiner JSP könntest du auch einfach JSTL (diese Taglib musst du aber explizit einbinden) verwenden:

```
<c:forEach var="item" items="${requestScope.meineList}">
    <input type="text" value="${item.valueAttr}" name="${item.nameAttr}" />
</c:forEach>
```
Hier noch der Link zum JavaEE Tutorial / JSTL: Core Tag Library - The Java EE 5 Tutorial

Ist halt nicht der saubere Struts Ansatz (manuelles setzen des Objekts in den Request...)...


----------



## =_=_= (28. Mai 2009)

Ich arbeite mit Struts2.

Ich habs aber nun geschafft, auf meine Liste zuzugreifen, auf folgende Art:


```
<s:iterator id="element"  value="elementPropertyList">
	<s:property value="getAttributeValue('id')" />	//Hier greife ich auf die ID des Elements zu
	<s:property value="name"/>			        //Und hier auf den Namen
</s:iterator>
```


In meinem Sourcecode wird injeder Iteration natürlich noch ein HTML <input> Feld generiert und die ausgelesenen Werte werden dann in die entsprechenden "value" und "id" Attribute geschrieben.

Das klappt auch alles wunderbar.

Nun treten zwei Probleme auf:

1. Die generierten Elemente reagieren nicht auf JavaScript Aktionen. Soll heissen: ich kann mit JavaScript neue <input> Elemente generieren, aber die Elemente die beim Auslesen aus der DB generiert wurden lassen sich im selben Formular nicht per JavaScript ansprechen bzw. andersrum gedacht: JavaScript aktionen lassen sich von diesen Elementen aus nicht aufrufen.

und

2. Speicher ich das gerade ausgelesene Formular erneut (so wie ich es mit komplett neu angelegten Objekten mache) dann klappt die Speicherung zwar aber es werden in meine XML Datei keine XML Elemente geschrieben, nach dem ersten ROOT Element in meiner XML  bricht der Schreibvorgang OHNE jegliche Exception ab.

das heisst meien XML sieht nach der erneuten Speicherung aus dem geladenen Formular so aus:

[XML]
<?xml version="1.0" encoding="UTF-8"?>
<Eigenschaften name="TESTTESTTEST" />
[/XML]

statt so:

[XML]
<?xml version="1.0" encoding="UTF-8"?>
<Eigenschaften name="TESTTESTTEST">
  <element1 id="0?">
    <subElement1 id="0?0" />
  </element1>
  <element2 id="1?" />
</Eigenschaften>
[/XML]


Ich suche nach dem Fehler bin aber gerade unsicher, was überhaupt der Auslöser sein könnte. Ich vermute, dass die generierten <input> Elemente nicht in den DOM Baum eingehängt werden... ???:L


Gruss


----------



## =_=_= (28. Mai 2009)

Was ich gerade gefunden habe ist diese Konsolenausgabe:


```
28.05.2009 10:55:02 org.apache.tomcat.util.http.Parameters processParameters
WARNUNG: Parameters: Invalid chunk ignored.
```


Wie gesagt das passiert NUR wenn ich eine XML speichern/schreiben will, die zuvor ins Formular geladen wurde. Bei einer völlig neuen XML Struktur klappt alles problemlos.


----------



## Noctarius (28. Mai 2009)

Ich muss ja gestehen, dass wenn ich "xml parsen, id auslesen und html generieren" lese ich sofort an XSLT denken muss


----------



## =_=_= (28. Mai 2009)

Na ja, 

nach Java, Hibernate, Struts, DisplayTag, JavaScript, HTML, CSS, XML, Tomcat und Datenbank würde mir das dann auch so langsam zu viel werden.


----------



## =_=_= (4. Jun 2009)

Hi. =)

Ich meld mich nochmal zu meinem Thema, da ich bisher nicht zu einem akzeptablen Ergebnis gekommen bin.  

Folgendes Problem besteht für mich aktuell:

Ich lese meine XML Daten aus der Datenbank und generiere mit meinem SAX-Builder eine neues XML Dokument im Speicher.

Das klappt auch soweit und ich kann auf meine Elemente zugreifen, jedoch hab ich das Problem der HTML Generierung.

Wie schon beschrieben erfolgt der Schritt zum Speichern der Daten in der Datenbank im Vorfeld durch die dynamische Generierung der Formularelemente mittels JavaScript. Das geht problemlos, alle Elemente hängen in meinem DOM Baum. Eindeutige IDs sind verteilt und die daraus resultierende XML Datei ist soweit auch OK.

Meine reine HTML Struktur sieht also mit einem generierten Beispielformular so aus:


```
<div id="root">
	<div id="a1_0">
		<input type="text" id="input_a1_0" />
	
		<div id="b1_0">
			<input type="text" id="input_b1_0" />
		</div>
		<div id="b1_1">
			<input type="text" id="input_b1_1" />
		</div>
	</div>
	<div id="a1_1">
		<input type="text" id="input_a1_1" />
		
		<div id="b1_2">
			<input type="text" id="input_b1_2" />
		</div>
	</div>
</div>
```


Ich habe alle Parameter au den <input> Elementen die unnötig sind rausgelassen damit es übersichtlicher bleibt.

So, meine daraus generierte XML sieht nun so aus:

[XML]
<?xml version="1.0" encoding="UTF-8"?>
<Elements name="test">
  <A id="0$">
    <a1 id="0$0" />
    <a1 id="0$1" />
  </A>
  <B id="1$">
    <b1 id="1$2" />
  </B>
</Elements>
[/XML]


Die internen IDs (also alle ZAHL $ ZAHL IDs) generiere ich mir um meien Elemente in Java ansprechen und filtern zu können, was ich ja chon beschrieben hatte in anderen Postings.

Wenn ich den Weg nun zurück gehe, also meine XML auslese, dein Dokument erstelle und dieses dann als Grundlage für die Generierung eines neuen HTML Formulars benutze, dann komme ich nicht über den Punkt hinaus, mir mein HTML Formular statisch zusammen zu bauen was aber ja in keinem Fall dem Grundaufbau des Originalformulars entspricht.

Nun überlege ich wie ich das machen soll. XSLT erscheint mir grade nicht passend, da meine Daten für das Formular ja schon so vorhanden sein sollten dass ich das Formular problemlos generieren kann. 

Dazu überlege ich, ob ich meinen XML Elementen nicht einfach ALLE IDs meiner HTML Elemente mitgeben soll, um diese dann auslesen zu können für mein neues Formular. 

Aber:

Wie soll ich das neue Formular genau generieren? Soll ich im HTML Body einen "onload" Aufruf setzen und wieder mit JavaScript das Formular aus meinem DOM Baum generieren? 

Oder ist das was ich überlege von hinten durch die Brust ins Auge? 

Bin im Moment etwas ratlos, da ich mich gedanklich etwas verstrickt habe in den Vorgängen...


Gruss

=_=_=


----------



## Noctarius (4. Jun 2009)

Wie bereits erwähnt XLST!


----------

