我有一系列相互配合的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文档需要进行多次连续转换时,请确保避免不必要的解析操作。我经常遇到将一个字符串转换为另一个字符串,然后将该字符串转换为另一个字符串的代码。这样不仅速度很慢,而且还会消耗大量内存,尤其是在不允许对中间字符串进行垃圾回收的情况下。
大多数转换基于一系列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.