Writing XSLT output to the multiple objects in memory

北城余情 提交于 2019-12-25 01:04:38

问题


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"));
}

}


回答1:


You need to define an OutputURIResolver - this is a Saxon-specific interface that is called to determine the destination for the output of xsl: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 call getUnderlyingController().setOutputURIResolver(), supplying your OutputURIResolver as the argument.



来源:https://stackoverflow.com/questions/47652132/writing-xslt-output-to-the-multiple-objects-in-memory

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!