能否在XSLT样式表中嵌入转换执行时运行的XQuery代码
实现思路
你根本不需要在XSLT流程里单独嵌入XQuery执行逻辑——XSLT 3.0 本身具备和XQuery完全同源的序列遍历、节点构造能力。之前你尝试时出现“XQuery代码被当文本直接输出”的问题,本质是把XQuery语法直接写在了XSLT模板的纯文本输出流里,处理器不会把这些非指令内容识别为可执行代码。
问题本质
- 你之前写的
{ (: xQuery-code :) }片段,被放在xsl:template的纯文本输出区域,XSLT只会把这类内容作为要渲染的普通文本打到最终HTML页面,自然不会执行其中的查询逻辑 - 你需要的“每次浏览器打开文档触发XSLT转换时,自动统计所有
<distinct>标签生成最新表格”的能力,完全可以用XSLT原生特性实现,不需要拆分XSLT和XQuery两个独立的执行流程
可直接落地的实现
当浏览器触发XSLT转换时,XSLT处理器加载的源文档本身就是存放TEI内容的XML文件,不需要额外调用doc()函数重复加载,直接遍历当前文档的目标节点即可:
- 在TEI源文档的研究内容区,给需要动态生成表格的位置加上标记,比如
<table type="query"></table> - 在现有XSLT里新增对应的匹配模板,完全复现你原本写的XQuery查询逻辑:
<!-- 匹配所有标记为需要动态生成的表格占位符 --> <xsl:template match="table[@type='query']"> <table class="dynamic-distinct-table"> <!-- 固定表头 --> <tr> <td>Verse Number</td> <td>Interesting Stuff</td> </tr> <!-- 遍历文档中所有<distinct>节点,和原XQuery的for循环逻辑完全等价 --> <xsl:for-each select="//distinct"> <tr> <!-- 取当前distinct节点所属行的行号,对应原XQuery的data($case/ancestor::l/@n)逻辑 --> <td><xsl:value-of select="ancestor::l[1]/@n"/></td> <!-- 原样输出distinct节点的全部内容,和原XQuery的单元格输出效果一致 --> <td><xsl:copy-of select="."/></td> </tr> </xsl:for-each> </table> </xsl:template>
如果使用适配浏览器场景的XSLT 3.0处理器(如SaxonJS),甚至可以直接沿用你原本的XQuery风格循环语法,写出来的代码和XQuery几乎没有区别:
<xsl:template match="table[@type='query']"> <table class="dynamic-distinct-table"> <tr> <td>Verse Number</td> <td>Interesting Stuff</td> </tr> <!-- XSLT 3.0原生支持XQuery风格的序列构造语法,不需要额外引擎 --> <xsl:sequence select=" for $case in //distinct return <tr> <td>{$case/ancestor::l[1]/@n}</td> <td>{$case}</td> </tr> "/> </table> </xsl:template>
方案和需求的匹配度
- 动态同步能力:每次校订修改史诗内容(包括新增、删除、调整
<distinct>标记),下次打开XML触发XSLT转换时,表格会自动重新遍历生成最新内容,完全不需要手动把生成的表格粘回TEI源文档 - 现有流程兼容:这套逻辑可以直接嵌入你已经跑通的TEI转HTML XSLT流程,和你之前处理静态表格的逻辑完全一致,不需要额外新增XQuery执行环节
- 适配浏览器触发场景:只要用SaxonJS作为浏览器端的XSLT处理器,不需要服务端参与,就能实现“打开XML自动完成转换、生成最新动态表格”的效果
内容的提问来源于stack exchange,提问作者Madlaina Brugger
相关产品推荐
相关产品推荐

