如何在 Java 中链接 XSLT 处理器?

Posted

技术标签:

【中文标题】如何在 Java 中链接 XSLT 处理器?【英文标题】:How to chain XSLT processors in Java? 【发布时间】:2021-12-16 13:35:38 【问题描述】:

我想用 Java 中的几个 XSLT 转换器执行链式 XML 处理。第一个转换器将输入作为javax.xml.transform.Source 并产生javax.xml.transform.Result。不是我想将结果用作下一次转换的输入。 IE。我需要第二次转换的来源。

如何从Result 创建Source(如果可能的话)?还是有其他解决方案可以解决我想做的事情?

【问题讨论】:

如果没记错的话,输入不是转换 XML 吗? Transform 的输出不也是 XML 吗?您不能直接从Result 对象中获取XML,然后将其分配给下一个Source 对象吗? 创建第二个 XSLT 作为 SAX TransformerHandler 并将其作为 SaxResult 提供给第一个 Transformer。 【参考方案1】:

一种方法是将第二个转换设置为 Sax TransformerHandler 作为第一个 TransformerSAXResult 的 ContentHandler,例如:

    TransformerFactory transformerFactory = TransformerFactory.newInstance();

    String xslt1 = "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'><xsl:template match='/'><xsl:call-template name='identity'/><xsl:comment>sheet 1</xsl:comment></xsl:template><xsl:template name='identity' match='@* | node()'><xsl:copy><xsl:apply-templates select='@* | node()'/></xsl:copy></xsl:template></xsl:stylesheet>";

    String xslt2 = "<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'><xsl:template match='/'><xsl:call-template name='identity'/><xsl:comment>sheet 2</xsl:comment></xsl:template><xsl:template name='identity' match='@* | node()'><xsl:copy><xsl:apply-templates select='@* | node()'/></xsl:copy></xsl:template></xsl:stylesheet>";

    Transformer transformer1 = transformerFactory.newTransformer(new StreamSource(new StringReader(xslt1)));

    TransformerHandler transformer2 = ((SAXTransformerFactory)transformerFactory).newTransformerHandler(new StreamSource(new StringReader(xslt2)));
    transformer2.setResult(new StreamResult(System.out));
    
    transformer1.transform(new StreamSource(new StringReader("<root><item>a</item><item>b</item></root>")), new SAXResult(transformer2));

或者您可以将 XSLT 转换链接为 SAX XMLFilters: https://saxonica.plan.io/projects/saxon/repository/he/revisions/master/entry/latest10/samples/java/he/JAXPExamples.java#L694

【讨论】:

非常酷,谢谢!这样就可以链接任意数量的 XSL 进程。只需将 SAXResult 添加到链中!我唯一不太喜欢的是对SAXTransformerFactory 的沮丧。我们能始终确保我们得到它的一个实例吗? @fml2,我认为您可以先检查该功能是否受支持,我需要查看 API 规范才能说明这一点,或许您可以查看 github.com/apache/xalan-java/blob/master/samples/Pipe/… 我想我可以检查是否transformerFactory instanceof SAXTransformerFactory,如果没有,使用序列化到字符串。我希望这永远不会发生。 @fml2,我不知道所有不同的 Java JRE 和 JDK(Oracle、IBM 等?)以及它们的内置 XSLT TransformerFactory 实现,足以判断您是否可以期望 SAXTransformerFactory支持,我认为 Xalan 支持,Saxon 也支持。

以上是关于如何在 Java 中链接 XSLT 处理器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Java 应用程序中使用 XSLT 3.0?

支持 XPath 2.0 的 Java XSLT 处理器

如何检查 Solr 中使用了哪个 XSLT 处理器?

除了使用扩展之外,如何在 XSLT 中处理自定义命名空间? [复制]

xslt 1.0中的嵌套分组

XSLT:如何使用 XSLT 1.0 和 XALAN 处理器转换部分转义的 XML?