使用SAXON EE10.6流式转换大XML为Solr格式报XTSE3430错误如何解决
报错原因分析
XTSE3430错误触发的核心是Saxon流式XSLT的强制规则:单个流式输入节点只能被消费一次。你的现有模板同时对同一个
record节点做了两个消费操作:
- 直接读取当前节点的属性构造
<field>元素- 调用
xsl:apply-templates处理当前节点的子节点
两次消费需要重复读取同一个流式节点的内容,不符合流式处理的单次访问要求,同时返回结果中直接引用未物化的流式节点,也会触发规则冲突。
适配流式处理的调整方案
你可以通过先物化单条record节点的方式解决问题,单条业务数据的体积通常在KB级别,完全不会占用过多内存,同时能规避流式节点的重复消费限制,修改逻辑如下:
- 根模板仅做流式遍历,不保留全文档树
<xsl:template match="/"> <add> <xsl:apply-templates select="/root/record" mode="streamed"/> </add> </xsl:template>
- 流式匹配
record节点后先物化,后续所有操作都基于物化后的变量执行
<xsl:template match="record" mode="streamed"> <!-- 单次消费流式节点,将整份record物化到内存 --> <xsl:variable name="current-record" select="copy-of(.)" as="element(record)"> <doc> <!-- 所有属性读取都从物化变量获取 --> <field name="id">{$current-record/@id}</field> <field name="type">{$current-record/@type}</field> <!-- 子节点处理也基于物化变量,不再操作原始流式节点 --> <xsl:apply-templates select="$current-record/*" mode="solr-field"/> </doc> </xsl:template>
- 其余处理子节点的模板不需要使用流式模式,直接操作物化后的节点内容即可。
运行验证注意事项
- 确保所有
mode="streamed"的模板中,对原始流式节点仅做一次操作,不要同时执行读属性、遍历子节点等多种操作 - Saxon EE调用时需要开启流式参数,命令行调用时添加
-stream:on即可 - 调整后转换内存占用会稳定在几十MB级别,不会随源文件体积增长,可支撑10GB以上的大XML文件处理。
内容的提问来源于stack exchange,提问作者Marco Duindam
相关产品推荐
相关产品推荐

