【问题标题】:Efficient XSLT pipeline in Java (or redirecting Results to Sources)Java 中的高效 XSLT 管道(或将结果重定向到源)
【发布时间】:2009-08-21 14:47:43
【问题描述】:

我有一系列相互馈送的 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 这样的项目,如果你还没有看过的话,这很酷,但我不想投资整个框架。

【问题讨论】:

  • "for(Transformer autobot : autobots){" 无价 :-)

标签: java xslt dom sax pipeline


【解决方案1】:

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

当多个时,连续 需要进行转换 同一个 XML 文档,一定要避免 不必要的解析操作。一世 经常遇到的代码 将一个字符串转换为另一个字符串, 然后将该字符串转换为尚未 另一个字符串。这不仅慢, 但它可以消耗大量 内存量也是如此,尤其是 如果中间字符串不是 允许被垃圾回收。

大多数转换都基于 一系列 SAX 事件。 SAX 解析器 通常会解析 InputStream 或 另一个 InputSource 到 SAX 事件中, 然后可以将其馈送到 变压器。而不是拥有 变压器输出到文件、字符串、 或另一个这样的结果,一个 SAXResult 可以代替使用。 SAX结果 接受一个 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.

【讨论】:

  • 太棒了,这看起来正是我正在寻找的。只是好奇-您搜索了什么来找到它?我的 google-foo 一定生锈了。
  • 其实,你的问题让我想起了前段时间看到的一些代码。我知道它使用了 saxtransformerfactory,所以我在 Google 上搜索:“saxtransformerfactory 链转换”。考虑到当您想要管道转换时它节省了多少代码/逻辑/麻烦,它似乎确实很难找到。
  • 根据onjava.com/pub/a/onjava/excerpt/java_xslt_ch5/?page=6,可以测试 transFact.getFeature(SAXTransformerFactory.FEATURE) 是否能够安全地转换为 SAXTransformerFactory。
  • 不应该关闭从 getResourceAsStream 获得的流吗?对我来说,这看起来像是资源泄漏。
【解决方案2】:

相关问题Efficient XSLT pipeline, with params, in Java 澄清了传递给此类转换器链的正确参数。

它还暗示了没有第三个变压器的稍微短一点的解决方案:

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

【讨论】:

    【解决方案3】:

    最好的办法是坚持使用 DOM,因为 XSLT 处理器无论如何都必须构建一棵树 - 流式传输只是非常有限的转换类别的一种选择,几乎没有处理器可以解决它自动切换到仅流式实现;否则他们只会读取输入并构建树。

    【讨论】:

    • 这是不正确的。行为取决于实现。 Java W3C DOM 实现效率非常低,大多数实现使用该 DOM 的更有效的内部表示。因此,接受的答案确实比“坚持 DOM”提高了性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-28
    • 1970-01-01
    相关资源
    最近更新 更多