2009-06-08 9 views
4

Angenommen, ich möchte eine große Menge von Suchergebnissen als XML in einen PrintWriter oder einen OutputStream mit XOM ausgeben. Das resultierende XML würde wie folgt aussehen:Wie streamen XML-Daten mit XOM?

<?xml version="1.0" encoding="UTF-8"?> 
<resultset> 
    <result> 
     [child elements and data] 
    </result> 
    ... 
    ... 
    [1000s of result elements more] 
</resultset> 

Da das resultierende XML-Dokument groß sein könnte (Hunderte von Megabytes, vielleicht), ich will es in einem Streaming-Mode-Ausgang (anstelle das gesamte Dokument im Speicher zu schaffen und dann schreibe ich das).

Die Granularität der Ausgabe von einem <result> zu einem Zeitpunkt ist in Ordnung, also möchte ich einen <result> nach dem anderen erzeugen, und schreibe es in den Strom. Mit anderen Worten, ich würde einfach gerne so etwas wie dieser Pseudo-Code tun (automatische Spülung aktiviert ist, also keine Sorge darüber):

open stream/writer 
write declaration 
write start tag for <resultset> 
while more results: 
    write next <result> element 
write end tag for <resultset> 
close stream/writer 

Ich habe bei Serializer, aber die notwendigen Methoden suchen, writeStartTag(Element) , writeEndTag(Element), write(DocType) sind geschützt, nicht öffentlich! Gibt es keinen anderen Weg, als den Serializer von der Unterklasse zu trennen, um diese Methoden verwenden zu können, oder um die Start- und End-Tags manuell als Strings in den Stream zu schreiben und dabei XOM zu umgehen? (Letzteres wäre in diesem einfachen Beispiel nicht allzu schlecht, aber im allgemeinen Fall würde es ziemlich hässlich werden.)

Fehle ich etwas oder ist XOM einfach nicht dafür gemacht?

Mit dom4j könnte ich dies tun leicht XMLWriter mit - es Konstrukteuren hat, dass ein Writer oder OutputStream nehmen und Methoden writeOpen(Element), writeClose(Element), writeDocType(DocumentType) usw. vergleichen zu XOM der Serializer wo die einzige öffentliche write Methode derjenige ist, der eine nimmt ganz Document.

(Dies ist auf my question about the best dom4j replacement bezogen, wo XOM ein starker Anwärter ist.)

Antwort

8

ich in auf der gleichen Ausgabe lief, aber foun d es ist ziemlich einfach zu tun, was man als eine Option und Unterklasse Serializer erwähnt wie folgt:

public class StreamSerializer extends Serializer { 

    public StreamSerializer(OutputStream out) { 
     super(out); 
    } 

    @Override 
    public void write(Element element) throws IOException { 
     super.write(element); 
    } 

    @Override 
    public void writeXMLDeclaration() throws IOException { 
     super.writeXMLDeclaration(); 
    } 

    @Override 
    public void writeEndTag(Element element) throws IOException { 
     super.writeEndTag(element); 
    } 

    @Override 
    public void writeStartTag(Element element) throws IOException { 
     super.writeStartTag(element); 
    } 

} 

Dann können Sie immer noch die Vorteile der verschiedenen XOM Config wie setIdent nehmen usw.aber es wie folgt verwendet werden:

Element rootElement = new Element("resultset"); 
StreamSerializer serializer = new StreamSerializer(out); 
serializer.setIndent(4); 
serializer.writeXMLDeclaration(); 
serializer.writeStartTag(rootElement); 
while(hasNextElement()) { 
    serializer.write(nextElement()); 
} 
serializer.writeEndTag(rootElement); 
serializer.flush(); 
+0

Ja, ich dachte, dass es so machbar sein sollte, aber nie herumkommen, es zu versuchen. Danke für die Bestätigung! In gewisser Hinsicht ist dies vorzuziehen, wenn man eine weitere Bibliothek von Drittanbietern (vgl. Peters Antwort) einführt, um einfach zu streamen. (Immerhin schade, dass XOM nicht mit diesem eingebauten kommt.) – Jonik

+0

In beiden Punkten vereinbart. –

+0

Schön. Ich mag deine Lösung und werde es nächstes Mal versuchen, wenn ich sie brauche. –

5

Soweit ich weiß, ist XOM nicht direkt Streaming unterstützen.

Was ich verwendet habe, wenn ich meine XML-Dokumente streamen wollte, war NUX, die Streaming XML Serializer hat, ähnlich wie Standard Serializer-Klasse in XOM. NUX ist kompatibel mit XOM. Ich habe NUX-Quellen heruntergeladen, wenige NUX-Klassen extrahiert (StreamingSerializer-Schnittstelle, StreamingXMLSerializer - was für XOM-Dokumente funktioniert, StreamingVerifier und NamespacesInScope), sie in mein Projekt eingefügt und es funktioniert wie ein Zauber. Schade ist dies nicht direkt in XOM :-(

NUX zu XOM sehr schön Begleiter ist: http://acs.lbl.gov/software/nux/, Spiegel arbeiten Download: nux-1.6.tar.gz

Link zur API: http://acs.lbl.gov/software/nux/api/nux/xom/io/StreamingSerializer.html

Hier ist Beispielcode (Methoden werden in der Reihenfolge genannt: start(), n * nextResult(), finish(), Serializer ist StreamingXMLSerializer von NUX):

void start() { 
    serializer.writeXMLDeclaration(); 

    Element root = new Element("response"); 
    root.addAttribute(new Attribute("found", Integer.toString(123))); 
    root.addAttribute(new Attribute("count", Integer.toString(542))); 

    serializer.writeStartTag(root); 

    serializer.flush(); 
} 

void nextResult(Result result) { 
    Element element = result.createXMLRepresentation(); 
    serializer.write(element); 
    serializer.flush(); 
} 

void finish() { 
    serializer.writeEndTag(); 
    serializer.flush(); 
} 
+1

Aktualisiert Link für Nux: http://acs.lbl.gov/software/nux/ –

+0

@Ed: Dank! Ich werde die Antwort aktualisieren. –

+1

Auch hier ist ein Download-Link, da ihre Website defekt ist und möglicherweise nicht gewartet: http://openbsd.mirrors.tds.net/pub/FreeBSD/distfiles/nux-1.6.tar.gz –