# XML-Stream als Quelle für FOP



## thommy.s (15. Dez 2010)

Hallo,

ich habe mir in einer Anwendung aus einer DB-Abfrage eine XML-Struktur gebaut, aus der ich per FOP-Engine ein PDF erzeugen will. Ich möchte aber die Struktur nicht als Datei zwischenspeichern, sondern die Struktur direkt verwenden.

Nun ja, mit JDOM konnte ich mir bislang nur einen OutputStream erzeugen, brauch aber als eine der beiden Quellen für  FOP (die andere ist die XSLT-Datei) einen InputStream. Ich habe zwar gelesen, dass man den OutStream in einen InputStream einlesen kann, dabei aber laut JavaDoc einen zweiten Thread erzeugen soll, um einem möglichen Deadlock vorzubeugen. Diese Vorgehensweise kommt mir doch sehr umständlich vor. 

Deshalb meine Frage: Geht es evt. auch anders, auf einem etwas eleganteren Weg, den ich bisher selbst nicht sehe?

Würde mich freuen,  wenn mir jemand das Brett vorm Kopf etwas lockern könnte.

Viele Grüße

Thomas


----------



## SlaterB (15. Dez 2010)

was verwendest du genau, TransformerFactory, Source, Result?

es gibt eine Klasse DOMSource, die kann mit einem DOM-Baum direkt umgehen, 
ansonsten müsstest du einen Zwischenschritt einbauen, der DOM in eine TXT-Form, eben XML, umwandelt,
was auch wieder TransformerFactory oder ähnliches leisten kann, 

da kommt dann zum Beispiel ein OutputStream raus, der als InputStream woanders dienen kann:
Convert a Java OutputStream to an InputStream
edit: ok, hast du auch schon geschrieben, 
ja Probleme gibts da schon, wenn alles ein Thread nacheinander macht dann werden eben erst die Daten geschrieben, 
wo sollen die hin wenn ein PipedOutputStream nur begrenzten Buffer hat und pausiert bis nicht irgendjemand (der zweite Thread) was ausliest?
mit Zwischenspeicherung in byte-Array oder Datei gibts dann aber gewiss weniger Probleme


----------



## thommy.s (15. Dez 2010)

danke dir schon mal für die Antwort.

Ich bin noch nicht so firm, was FOP angeht, deshalb kann ich dir leider noch gar nicht sagen, was ich denn verwenden werde. Wollte mir erst einmal die Ausgangsbedingungen schaffen, um dann mit FOP voll zuschlagen zu können. Die hab' ich nun soweit, nur dass ich eben einen InputStream brauche, um nicht mit dem Zwischenschritt XML-Datei arbeiten zu müssen. Die XSLT-Datei sollte kein größeres Problem werden, so hoffe ich.

Aber ich werde mal deinem Link folgen und es mit den pipes versuchen, obwohl ich's noch nicht so recht verstehe...

Grüße Thomas


----------



## thommy.s (17. Dez 2010)

hab es nun, aus meiner Sicht wesentlich einfacher, gelöst:

Den OutputStream in ein ByteArray gepackt, und dieses als Quelle für den InputStream benutzt, siehe:


```
public InputStream createXMLStream(int woche) {
		
		Properties p = new Properties();
		
		ByteArrayOutputStream pos = (ByteArrayOutputStream) this.prepareData(woche);
		
		try {
			
			p.store(pos, "");
			
		} catch (IOException e) {
			
			e.printStackTrace();
			
			return null;
		}
		
		ByteArrayInputStream xmlin = new ByteArrayInputStream(pos.toByteArray());
		
		return xmlin;
		
		
	}
```

Damit geht's spitzenmäßig.

Grüße Thomas


----------



## thommy.s (19. Dez 2010)

...allerdings tritt ein neues Problem auf, welches ich vorher nicht als solches angesehen habe:

der SAX-Parser meldet:


```
System-ID unbekannt; Zeilennummer25; Spaltennummer1; Content is not allowed in trailing section.
```

Hab mir das XML als Datei ausgegeben, unter dem letzten ausführenden Root-Tag ist in 'gedit' eine weitere Zeile zu sehen, die aber leer ist. Die Zeilennummer, bei der der Fehler gemeldet wird, ist die erste, die nicht mehr existiert. Mit anderen Worten, hat meine XML-Datei bis nach dem letzten </root>-Tag insgesamt 23 Zeilen, wird noch eine weitere leere Zeile (also 24) angehängt, der Parser meldet den Fehler in 'Zeile 25' (siehe oben).

Die Methode, die den XML-Stream schreibt, hier:


```
public OutputStream prepareData(int woche) {
		
		ByteArrayOutputStream bas = new ByteArrayOutputStream();
		
		
		
		Document doc = new Document();
		
								
		ResultSet rs_ready = getResultSet(woche);
		
		try {
			
			Element root = new Element("root");
			
			String akt_datum = "";
			
			Element elDatum = null;
			
			while (rs_ready.next()){			
				
				if (!(rs_ready.getDate("datum").toString().equals(akt_datum))) {
					
					akt_datum = rs_ready.getDate("datum").toString();
					
					elDatum = new Element ("datum");
					
					elDatum.addContent(akt_datum);		
					
					root.addContent(elDatum);
										
				}					
				
				
				Element elDoing = new Element("taetigkeit");
					
				elDoing.addContent(rs_ready.getString("aktivitaet"));
				elDoing.setAttribute("kategorie", rs_query.getString("kategorie"));
				elDoing.setAttribute("auftraggeber", rs_query.getString("auftraggeber"));
				elDoing.setAttribute("von", rs_query.getString("von"));
				elDoing.setAttribute("bis", rs_query.getString("bis"));
				
				elDatum.addContent(elDoing);
				
				
				
			}
			
			doc.setRootElement(root);
			
			try {
			
				XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
				
				
				//DOMOutputter domout = new DOMOutputter().output(doc);
				//OutputStream output = new OutputStream("/file.xml");
		    
				outputter.output(doc,bas);
				
				outputter.output(doc, new FileOutputStream("out.xml", false));
				
				
				
			} catch (IOException e) {
				
				e.printStackTrace();
				
				return null;
			}
			
		} catch (SQLException e) {
			
			e.printStackTrace();
			
			return null;
		}
		
		return bas;
	}
```


Ich weiß nicht, wo diese letzte leere Zeile herkommt; lösche ich sie und verwende so die XML-Datei als Quelle, funktioniert es. 

Warum wird hier eine Zeile zuviel geschrieben?

Ratlosigkeit

Thomas
	
	
	
	





```

```


----------

