Java中如何实现多个XSLT处理器的链式调用?
Java XSLT链式转换实现方案
核心结论:无法直接从通用的
javax.xml.transform.Result接口实例创建Source对象。Result本身仅为标记接口,不提供内容访问能力,你可以根据使用场景选择以下两种成熟方案实现链式转换。
方案一:内存缓存中转(适合小体积XML)
该方案逻辑简单易实现,通过内存缓冲区存储第一次转换的输出,再转为输入源供第二次转换使用:
import javax.xml.transform.*; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; public class XsltChainDemo1 { public static void main(String[] args) throws Exception { // 初始化转换器工厂和两个XSLT转换器 TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer1 = factory.newTransformer(new StreamSource(new FileInputStream("xslt1.xsl"))); Transformer transformer2 = factory.newTransformer(new StreamSource(new FileInputStream("xslt2.xsl"))); // 第一次转换输出到内存字节数组 ByteArrayOutputStream buffer = new ByteArrayOutputStream(); transformer1.transform(new StreamSource(new FileInputStream("input.xml")), new StreamResult(buffer)); // 内存中转内容转为输入源,执行第二次转换 StreamSource secondInput = new StreamSource(new ByteArrayInputStream(buffer.toByteArray())); transformer2.transform(secondInput, new StreamResult(new FileOutputStream("output.xml"))); } }
- 优点:代码逻辑直观,不需要额外依赖,适配所有
Result实现类 - 缺点:需要做中间结果的序列化/反序列化,大体积XML会占用较高内存,性能偏低
如果第一次转换你使用的是DOMResult输出,可以直接复用DOM节点无需序列化:
DOMResult firstResult = new DOMResult(); transformer1.transform(inputSource, firstResult); // 直接从DOM节点创建Source,无额外性能损耗 Source secondInput = new DOMSource(firstResult.getNode());
方案二:SAX事件流链式处理(适合任意体积XML,性能最优)
该方案基于SAX事件流实现,无需中间缓存,第一次转换产生的事件直接喂给第二个转换器处理,内存占用极低,适合处理GB级大XML:
import javax.xml.transform.TransformerFactory; import javax.xml.transform.sax.SAXResult; import javax.xml.transform.sax.SAXTransformerFactory; import javax.xml.transform.sax.TransformerHandler; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import org.xml.sax.helpers.XMLReaderFactory; public class XsltChainDemo2 { public static void main(String[] args) throws Exception { // 初始化SAX转换工厂 SAXTransformerFactory saxFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); // 创建两个转换器的事件处理Handler TransformerHandler handler1 = saxFactory.newTransformerHandler(new StreamSource("xslt1.xsl")); TransformerHandler handler2 = saxFactory.newTransformerHandler(new StreamSource("xslt2.xsl")); // 绑定链式处理关系:handler1的输出事件直接传给handler2,handler2输出到最终文件 handler1.setResult(new SAXResult(handler2)); handler2.setResult(new StreamResult("output.xml")); // 启动解析执行转换 XMLReader reader = XMLReaderFactory.createXMLReader(); reader.setContentHandler(handler1); reader.parse(new InputSource("input.xml")); } }
- 优点:无中间缓存,内存占用极低,没有序列化/反序列化开销,性能远高于内存中转方案
- 缺点:代码复杂度略高于方案一,需要了解SAX事件模型的基础逻辑
内容的提问来源于stack exchange,提问作者fml2
相关产品推荐
相关产品推荐

