I'm playing with XSLT and writing the result to the multiple outputs in Java as these links describe: link1, link2.
When it comes to writing to the files everything works perfectly, but now I'd like to store the output XMLs as either Document object or some kind of InputStream/String - anything but file on a drive. Writing the documents to the files using Transformer and than reading them to the objests(Document, String etc.) is not an option.
My question is: what should I change in my xslt map and java code to get the output as an objects, not the files on a drive. (the only solution that I came up with is to use two XSLT on this one XML but it's not the elegant way)
My Java codes are similar to the answers in the links above. I'm using XSLT 2.0 and transform using :
transformer.transform(xmlText, new DOMResult());
I also added
<xsl:result-document href="{concat($jobName, '_assets.xml')}">
<xsl:apply-templates select="GetMetadata/Metadata" mode="assets"/>
</xsl:result-document>
<xsl:result-document href="{concat($jobName, '_flows.xml')}">
<xsl:apply-templates select="GetMetadata/Metadata" mode="flows"/>
</xsl:result-document>
to my xsl map [writing to the files works fine]
LATER
Correct implementation: (thank you Michael)
public void multipleXMLExtractor(Document inputDom, String xsltPath) throws TransformerException, UnsupportedEncodingException {
Source xmlInput = new DOMSource(inputDom);
Source xsltMap = new StreamSource(new File(xsltPath));
final Map<String, StreamResult> resultsMap = new HashMap<String, StreamResult>();
resultsMap.put("output1", new StreamResult(new ByteArrayOutputStream()));
resultsMap.put("output2", new StreamResult(new ByteArrayOutputStream()));
TransformerFactory tFactory = TransformerFactory.newInstance("net.sf.saxon.TransformerFactoryImpl", XMLviaXSLTransformer.class.getClassLoader());
Transformer transformer = tFactory.newTransformer(xsltMap);
((net.sf.saxon.jaxp.TransformerImpl) transformer).getUnderlyingController().setOutputURIResolver(new OutputURIResolver() {
@Override
public OutputURIResolver newInstance() {
return this;
}
@Override
public Result resolve(String s, String s1) throws TransformerException {
return resultsMap.get(s);
}
@Override
public void close(Result result) throws TransformerException {
}
});
StreamResult standardResult = new StreamResult(new ByteArrayOutputStream());
transformer.transform(xmlInput, standardResult);
for (Map.Entry<String, StreamResult> stringStreamResultEntry : resultsMap.entrySet()) {
System.out.println(stringStreamResultEntry.getKey() + ": " + ((ByteArrayOutputStream) stringStreamResultEntry.getValue().getOutputStream()).toString("UTF-8"));
}
}
You need to define an
OutputURIResolver
- this is a Saxon-specific interface that is called to determine the destination for the output ofxsl:result-document
. It is given a URI as input, and returns a JAXP Result object to which the result document will be written.https://www.saxonica.com/documentation/index.html#!javadoc/net.sf.saxon.lib/OutputURIResolver
If you're using the JAXP API to control the transformation, you will have to cast the Transformer object to
net.sf.saxon.jaxp.TransformerImpl
, and then callgetUnderlyingController().setOutputURIResolver()
, supplying yourOutputURIResolver
as the argument.