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

Java中高效的XSLT管道(或将结果重定向到源代码),java,xslt,dom,sax,pipeline,Java,Xslt,Dom,Sax,Pipeline,我有一系列的XSL 2.0样式表,它们相互馈送,即样式表a的输出馈送B馈送C 最有效的方法是什么?重新表述的问题是:如何有效地将一个转换的输出路由到另一个 这是我的第一次尝试: @Override public void transform(Source data, Result out) throws TransformerException{ for(Transformer autobot : autobots){ if(autobots.indexOf(autobo

我有一系列的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来处理转换之间的关系,虽然这很方便,但在性能方面不是最优的

有没有简单的路由方法,比如说,将SAXSresult路由到SAXSource?StAX解决方案将是另一种选择


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

你最好的选择是在做的时候坚持使用DOM,因为XSLT处理器无论如何都必须构建一个树-流式处理只是非常有限的转换类别的一个选项,很少有处理器能够自动解决这个问题,并切换到只支持流媒体的实现;否则,他们只需读取输入并构建树。

我发现:这显示了使用TransformerFactory来链接转换的两种方法,将一个转换的结果馈送到下一个转换,然后最终输出到system out。这避免了在转换之间对字符串、文件等进行中间序列化的需要

当有多个时,是连续的 需要对 相同的XML文档,请确保避免 不必要的解析操作。我 经常遇到这样的代码 将一个字符串转换为另一个字符串, 然后将该字符串转换为 另一串。不仅是这么慢,, 但它可以消耗大量的能源 内存量也很大,尤其是 如果中间字符串不是 允许垃圾收集

大多数转换都基于 一系列SAX事件。SAX解析器 通常将解析InputStream或 SAX事件中的另一个输入源, 然后可以将其馈送到 变压器。而不是 转换器输出到文件、字符串、, 或者另一个这样的结果,一个结果 可以改用。结果 接受ContentHandler,它可以 将这些SAX事件直接传递给 另一台变压器等

这里有一种方法,也是我想要的 通常更喜欢,因为它提供了更多 灵活处理各种输入和输出 输出源。这也使它成为现实 创建转换相当容易 动态链接并使用变量 转换的数量

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.
澄清了有关传递至该变压器链的正确参数的相关问题

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

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

太好了,看起来正是我要找的。只是好奇-你是怎么找到的?我的GoogleFoo一定是生锈了。事实上,你的问题让我想起了我不久前看到的一些代码。我知道它使用了一个saxtransformerfactory,所以我在谷歌上搜索:“saxtransformerfactory链转换”。考虑到当您想要管道化转换时它节省了多少代码/逻辑/麻烦,这似乎很难找到。根据,您可以测试transFact.getFeature(SAXTransformerFactory.FEATURE)是否能够安全地强制转换到SAXTransformerFactory。您是否应该关闭从getResourceAsStream获得的流?对于(Transformer autobot:autobots){“Priceless:-)来说,这是不正确的。行为依赖于实现。Java W3C DOM实现效率非常低,大多数实现都使用此DOM的更高效的内部表示形式。因此,公认的答案确实提高了性能“坚持DOM”。