Hi,
I want to read records from a database and export it in an arbitrary
format.
My idea was to feed a class with a String array fetched from the
database and let
this class fire SAX events as processor input.
The basic class hierarchy is:
org.xml.sax.XMLReader [Interface]
^
|
|
AbstractXMLReader
^
/ \
|
|
|
StringArrayXMLReader --------------------> TransformerHandler
The TransformerHandler is associated with a StreamResult
(ByteArrayOutputStream)
and the XSL-Stylesheet.
In a first try I provided a init and close method for
StringArrayXMLReader which implements
startDocument()/endDocument() and some header information.
The problem is here that the xslt processing takes place on endDocument
and therefore all
rows from the database are buffered until endDocument is fired.
Because the result set from the database could be really large this is
not an option for me.
For recap:
fired SAX event was :
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<row><value>1-String</value><value>2-String</value><value>3-String</value></row>
<row><value>R1-String</value><value>R2-String</value><value>R3-String</value></row>
</dataset>
XSL was:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<table border="1">
<xsl:apply-templates select="dataset/row"/>
</table>
</xsl:template>
<xsl:template match="dataset/row">
<tr>
<xsl:apply-templates select="value"/>
</tr>
</xsl:template>
<xsl:template match="value">
<td>
<xsl:value-of select='.'/>
</td>
</xsl:template>
</xsl:stylesheet>
My next idea was to consider one row from the database result set as
one input document for
the processor and to provide the header information manually.
I also modified my XSL-Stylesheet and put the startDocument/endDocument
in the parse method.
Processor input is now:
<?xml version="1.0" encoding="UTF-8"?>
<row><value>1-String</value><value>2-String</value><value>3-String</value></row>
and XSL looks:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<tr>
<xsl:apply-templates select="row/value"/>
</tr>
</xsl:template>
<xsl:template match="value">
<td>
<xsl:value-of select='.'/>
</td>
</xsl:template>
</xsl:stylesheet>
Doing this now I get an NullPointerException in
org.apache.xalan.transformer.TransformerImpl.run
on the second call of my StringArrayXMLReader.parse method.
The first call looks OK. The fired SAX event is converted properly by
the XSLT-processor.
Beside this special problem I have the more general question:
Is it possible to transform XML with a xslt processor without having
the whole document in memory ?
Because my result set is very large I can not read it in memory.
I tried the SAX-fire event mechanism because I thought it gives me the
fewest overhead.
However consider a row as a complete document looks also not tidy
because now I lose the xslt
power for my header information.
Maybe I misunderstand here something completely.
How would a XML/XSLT expert solve the problem ?