使用XSLT转换XML时遭遇TransformerConfigurationException错误求助
解决XSLT转换时的TransformerConfigurationException问题
首先,你看到的Required attribute 'select' is missing错误是个误导性提示——你的<xsl:variable>明明带有select属性,真正的问题是你的XSLT使用了XSLT 2.0特性,但Java默认的XML转换引擎(Apache Xalan)只支持XSLT 1.0,无法解析你写的for表达式这类2.0语法,导致解析XSLT时抛出错误。
下面给你两种可行的解决方案:
方案1:改用支持XSLT 2.0的处理器(推荐)
最省心的方法是使用Saxon,它是目前主流的XSLT 2.0/3.0处理器,完美兼容你的现有代码。
步骤1:添加Saxon依赖
如果用Maven,在pom.xml中加入:
<dependency> <groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId> <version>12.4</version> <!-- 可替换为最新稳定版 --> </dependency>
如果是手动导入,下载Saxon-HE的jar包添加到项目类路径即可。
步骤2:修改Java代码指定Saxon工厂
在创建TransformerFactory前,明确指定使用Saxon的实现类:
package firstspring; import java.io.File; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class fileread { public static void main(String[] args) { // 配置使用Saxon的TransformerFactory System.setProperty("javax.xml.transform.TransformerFactory", "net.sf.saxon.TransformerFactoryImpl"); TransformerFactory tFactory = TransformerFactory.newInstance(); StreamSource xmlInputFile = new StreamSource("E:/test/test.xml"); StreamSource xslTransformationFile = new StreamSource("E:/test/my.xsl"); StreamResult xmlOutputFile = new StreamResult("E:/test/out.xml"); try { Transformer transformer = tFactory.newTransformer(xslTransformationFile); transformer.transform(xmlInputFile, xmlOutputFile); } catch (TransformerConfigurationException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } System.out.println("Done!"); } }
注:我修正了你原Java代码中缺失类定义的问题,确保代码可以正常编译运行。
方案2:将XSLT改写为XSLT 1.0兼容版本
如果你不想引入新依赖,可以把XSLT代码改成XSLT 1.0支持的写法,实现和原代码完全一样的功能:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="1.0"> <xsl:output omit-xml-declaration="yes" indent="no"/> <xsl:template match="/"> <value> <xsl:for-each select="//section"> <path> <!-- XSLT 1.0方式生成节点路径:遍历祖先节点拼接名称 --> <xsl:for-each select="ancestor::*"> <xsl:value-of select="name()"/> <xsl:text>/</xsl:text> </xsl:for-each> <xsl:value-of select="name()"/> </path> </xsl:for-each> </value> </xsl:template> </xsl:stylesheet>
这个版本用XSLT 1.0原生的xsl:for-each遍历祖先节点,逐个拼接节点名称,和你原XSLT 2.0代码的输出完全一致,不需要修改Java代码就能在默认的Xalan引擎下运行。
内容的提问来源于stack exchange,提问作者Reegan
相关产品推荐
相关产品推荐

