Java中的高效XSLT管道(或将结果重定向到源)

我有一系列相互馈送的XSL 2.0样式表,即样式表A的输出馈送B馈送C.

这样做最有效的方法是什么? 重新提出的问题是:如何有效地将一个转换的输出路由到另一个转换。

这是我的第一次尝试:

@Override public void transform(Source data, Result out) throws TransformerException{ for(Transformer autobot : autobots){ if(autobots.indexOf(autobot) != (autobots.size()-1)){ log.debug("Transforming prelim stylesheet..."); data = transform(autobot,data); }else{ log.debug("Transforming final stylesheet..."); autobot.transform(data, out); } } } private Source transform(Transformer autobot, Source data) throws TransformerException{ DOMResult result = new DOMResult(); autobot.transform(data, result); Node node = result.getNode(); return new DOMSource(node); } 

正如您所看到的,我正在使用DOM来处理转换之间,尽管它很方便,但它并不是非最佳性能。

是否有任何简单的方法可以说,将SAXResult路由到SAXSource? StAX解决方案将是另一种选择。

我知道像XProc这样的项目,如果你还没有看过,这是非常酷的,但我不想投资一个完整的框架。

我发现了这个: #3。 链接转换显示了两种使用TransformerFactory链转换的方法,让一个转换的结果提供下一个转换,然后最终输出到系统输出。 这避免了在变换之间对字符串,文件等进行中间序列化的需要。

当同一XML文档需要多次连续转换时,请务必避免不必要的解析操作。 我经常遇到将String转换为另一个String的代码,然后将该String转换为另一个String。 这不仅速度慢,而且还会占用大量内存,特别是如果不允许中间字符串被垃圾收集。

大多数转换都基于一系列SAX事件。 SAX解析器通常会将InputStream或另一个InputSource解析为SAX事件,然后可以将其提供给Transformer。 不是将Transformer输出到File,String或其他此类Result,而是可以使用SAXResult。 SAXResult接受ContentHandler,它可以将这些SAX事件直接传递给另一个Transformer等。

这是一种方法,也是我通常喜欢的方法,因为它为各种输入和输出源提供了更大的灵活性。 它还使得动态创建转换链并使用可变数量的转换变得相当容易。

 SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance(); // These templates objects could be reused and obtained from elsewhere. Templates templates1 = stf.newTemplates(new StreamSource( getClass().getResourceAsStream("MyStylesheet1.xslt"))); Templates templates2 = stf.newTemplates(new StreamSource( getClass().getResourceAsStream("MyStylesheet1.xslt"))); TransformerHandler th1 = stf.newTransformerHandler(templates1); TransformerHandler th2 = stf.newTransformerHandler(templates2); th1.setResult(new SAXResult(th2)); th2.setResult(new StreamResult(System.out)); Transformer t = stf.newTransformer(); t.transform(new StreamSource(System.in), new SAXResult(th1)); // th1 feeds th2, which in turn feeds System.out. 

你最好的选择是坚持使用DOM,因为XSLT处理器无论如何都必须构建一个树 – 流只是非常有限的转换类型的选项,如果有任何处理器可以自动解决它并且切换很少到仅限流媒体的实现; 否则他们只是读取输入并构建树。

相关问题在Java中使用params的高效XSLT管道澄清了传递给这种变换器链的正确参数。

它还提供了一个没有第三变压器的略短解决方案的提示:

 SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance(); Templates templates1 = stf.newTemplates(new StreamSource( getClass().getResourceAsStream("MyStylesheet1.xslt"))); Templates templates2 = stf.newTemplates(new StreamSource( getClass().getResourceAsStream("MyStylesheet2.xslt"))); TransformerHandler th1 = stf.newTransformerHandler(templates1); TransformerHandler th2 = stf.newTransformerHandler(templates2); th2.setResult(new StreamResult(System.out)); // Note that indent, etc should be applied to the last transformer in chain: th2.getTransformer().setOutputProperty(OutputKeys.INDENT, "yes"); th1.getTransformer().transform(new StreamSource(System.in), new SAXResult(th2));