Java中高效的XSLT管道(或将结果重定向到源) [英] Efficient XSLT pipeline in Java (or redirecting Results to Sources)

查看:165
本文介绍了Java中高效的XSLT管道(或将结果重定向到源)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一系列XSL 2.0样式表互相补充,即样式表A的输出提供B Feed C。



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



这是我的第一个尝试:



public void transform(Source data,Result out)throws TransformerException {
for(Transformer autobot:autobots){
if(autobots .indexOf(autobot)!=(autobots.size() - 1)){
log.debug(Transforming preliminary stylesheet ...);
data = transform(autobot,data);
} else {
log.debug(Transforming final stylesheet ...);
autobot.transform(data,out);
}
}
}

private源转换(Transformer autobot,Source data)throws TransformerException {
DOMResult result = new DOMResult();
autobot.transform(data,result);
Node node = result.getNode();
返回新的DOMSource(node);
}

如您所见,我正在使用DOM坐在转换之间,虽然方便,但它的性能是非最佳的。



有没有简单的方法来路由说SAXResult路由到SAXSource?一个StAX解决方案将是另一个选择。



我知道像 XProc ,如果还没有看过,那很酷,但是我不想投资整个框架。

解决方案

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


当多个连续的
转换是需要
相同的XML文档,一定要避免
不必要的解析操作。 I
经常运行到
将String转换为另一个String的代码中,
然后将该String转换为
另一个String。不仅是这个缓慢的
,而且它可以消耗大量的
的内存量,特别是
,如果中间字符串不是
被允许被垃圾回收。 p>

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



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

  SAXTransformerFactory stf =(SAXTransformerFactory)TransformerFactory.newInstance(); 

//这些模板对象可以从其他地方重复使用并获取。
模板templates1 = stf.newTemplates(new StreamSource(
getClass()。getResourceAsStream(MyStylesheet1.xslt)));
模板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),新的SAXResult(th1));

// th1 feed th2,这又反馈给System.out。



I have a series of XSL 2.0 stylesheets that feed into each other, i.e. the output of stylesheet A feeds B feeds C.

What is the most efficient way of doing this? The question rephrased is: how can one efficiently route the output of one transformation into another.

Here's my first attempt:

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

As you can see, I'm using a DOM to sit in between transformations, and although it is convenient, it's non-optimal performance wise.

Is there any easy way to route to say, route a SAXResult to a SAXSource? A StAX solution would be another option.

I'm aware of projects like XProc, which is very cool if you haven't taken a look at yet, but I didn't want to invest in a whole framework.

解决方案

I found this: #3. Chaining Transformations that shows two ways to use the TransformerFactory to chain transformations, having the results of one transform feed the next transform and then finally output to system out. This avoids the need for an intermediate serialization to String, file, etc. between transforms.

When multiple, successive transformations are required to the same XML document, be sure to avoid unnecessary parsing operations. I frequently run into code that transforms a String to another String, then transforms that String to yet another String. Not only is this slow, but it can consume a significant amount of memory as well, especially if the intermediate Strings aren't allowed to be garbage collected.

Most transformations are based on a series of SAX events. A SAX parser will typically parse an InputStream or another InputSource into SAX events, which can then be fed to a Transformer. Rather than having the Transformer output to a File, String, or another such Result, a SAXResult can be used instead. A SAXResult accepts a ContentHandler, which can pass these SAX events directly to another Transformer, etc.

Here is one approach, and the one I usually prefer as it provides more flexibility for various input and output sources. It also makes it fairly easy to create a transformation chain dynamically and with a variable number of transformations.

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.

这篇关于Java中高效的XSLT管道(或将结果重定向到源)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆