Apache Camel集成XQuery报错:参数类型不匹配问题求助
问题根源
Saxon对XQuery外部变量的类型检查极为严格,当你声明$configXML为element()类型时,要求传入的必须是关联当前查询上下文的Saxon原生XdmNode实例:
- 直接传入
org.w3c.dom.Document/Element对象时,Saxon无法将其识别为自身类型系统内的节点,会判定为外部对象 - 即使手动创建了
XdmNode,如果该实例未绑定到执行XQuery时使用的SaxonConfiguration上下文,同样会触发类型不匹配报错
解决办法
1. 确保依赖版本兼容(Java 17适配)
使用支持Java 17的Camel和Saxon版本,避免版本不兼容导致的隐性问题:
<dependencies> <!-- Camel Core --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-core</artifactId> <version>3.20.2</version> </dependency> <!-- Camel Saxon 组件 --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-saxon</artifactId> <version>3.20.2</version> </dependency> <!-- Saxon HE 11.x+ 支持Java 17 --> <dependency> <groupId>net.sf.saxon</groupId> <artifactId>Saxon-HE</artifactId> <version>11.6</version> </dependency> </dependencies>
2. 在Camel路由中正确转换XML为Saxon XdmNode
使用Saxon原生API将XML转换为绑定到当前Configuration的XdmNode,确保上下文一致:
import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.XdmNode; import org.apache.camel.builder.RouteBuilder; import org.w3c.dom.Document; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; public class XQueryIntegrationRoute extends RouteBuilder { // 初始化Saxon Processor(单例,绑定统一Configuration) private final Processor saxonProcessor = new Processor(false); @Override public void configure() throws Exception { from("file:data/in?fileName=Config.xml") .process(exchange -> { File configFile = exchange.getIn().getBody(File.class); // 开启命名空间感知,避免Saxon节点类型校验失败 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document domDoc = dbf.newDocumentBuilder().parse(configFile); // 将DOM转换为Saxon XdmNode,绑定到当前Processor的Configuration XdmNode xdmConfigNode = saxonProcessor.newDocumentBuilder().wrap(domDoc); exchange.setProperty("configXML", xdmConfigNode); }) // 通过#exchangeProperties传递外部变量到XQuery .to("saxon:test.xqy?variables=#exchangeProperties"); } }
3. 验证XQuery变量声明与使用
确保XQuery中的变量声明和逻辑匹配传入的节点类型,示例test.xqy:
declare variable $configXML as element() external; <!-- 示例逻辑:提取配置中的名称节点 --> <processed-config> <name>{data($configXML/config/name)}</name> <timeout>{data($configXML/config/timeout)}</timeout> </processed-config>
关键注意事项
- 必须开启
NamespaceAware:Saxon对XML命名空间处理严格,未开启会导致转换后的节点无法被识别为element()类型 - 复用Saxon Processor:避免在每个处理器中重复创建Processor,确保所有XdmNode都绑定到同一个Configuration上下文
- 变量传递方式:使用
variables=#exchangeProperties确保Exchange属性中的XdmNode被正确传入XQuery上下文
内容的提问来源于stack exchange,提问作者user29885133
相关产品推荐
相关产品推荐

