如何在Saxon XSLT中复用已解析的XdmItem文档避免重复解析?
Saxon 12复用已解析XdmNode实现高效XML处理
Saxon完全支持复用已解析的XdmNode(属于XdmItem类型)来执行多次XPath查询和XSLT转换,彻底避免重复解析XML文档,这对处理数万份XML的场景能带来显著的性能提升。
步骤1:将XML一次性解析为可复用的XdmNode
首先把XML输入流解析为XdmNode,这一步只需要执行一次,后续所有操作都基于这个已解析的节点树:
Processor processor = new Processor(false); DocumentBuilder docBuilder = processor.newDocumentBuilder(); // 从输入流解析XML,仅执行一次 InputStream xmlStream = ...; // 你的XML输入流 XdmNode parsedDocument = docBuilder.build(new StreamSource(xmlStream)); xmlStream.close(); // 解析完成后可关闭流
步骤2:复用XdmNode执行多次XPath查询
基于已解析的XdmNode,可以多次执行不同的XPath查询,无需重新解析:
// 预先编译XPath表达式(仅编译一次,可复用) XPathCompiler xpathCompiler = processor.newXPathCompiler(); XPathExecutable titleXpath = xpathCompiler.compile("//book/title"); XPathExecutable authorXpath = xpathCompiler.compile("//book/author"); // 基于同一XdmNode执行多次查询 XdmValue titles = titleXpath.load().evaluate(parsedDocument); XdmValue authors = authorXpath.load().evaluate(parsedDocument);
步骤3:复用XdmNode执行多次XSLT转换
这是你关心的核心点:Saxon的XSLT转换完全支持直接传入XdmNode作为源,无需每次都用StreamSource重新解析。具体实现如下:
// 预先编译多个XSLT样式表(仅编译一次,可复用) XsltCompiler xsltCompiler = processor.newXsltCompiler(); XsltExecutable transformToHtml = xsltCompiler.compile(new StreamSource(new File("xml-to-html.xsl"))); XsltExecutable transformToCsv = xsltCompiler.compile(new StreamSource(new File("xml-to-csv.xsl"))); // 复用同一XdmNode执行第一次转换 XsltTransformer htmlTransformer = transformToHtml.load(); htmlTransformer.setSource(parsedDocument); // 直接传入已解析的XdmNode htmlTransformer.setResult(new StreamResult(new File("output.html"))); htmlTransformer.transform(); // 复用同一XdmNode执行第二次转换 XsltTransformer csvTransformer = transformToCsv.load(); csvTransformer.setSource(parsedDocument); csvTransformer.setResult(new StreamResult(new File("output.csv"))); csvTransformer.transform();
关键注意事项
- 线程安全性:
XdmNode是不可变对象,可安全地在多线程环境中复用,适合并行处理数万份XML文档。 - 预编译优先:XPath表达式和XSLT样式表的编译过程相对耗时,预先编译后重复使用,能进一步放大性能收益。
- 内存管理:如果XML文档过大,需注意内存占用情况,可结合Saxon的分块处理特性平衡性能与内存,但对于常规大小的XML,复用
XdmNode是最优方案。
内容的提问来源于stack exchange,提问作者Garret Wilson
相关产品推荐
相关产品推荐

