如何优化eXist-db中的XSLT转换?大XML页面性能优化
问题描述
我用eXist数据库,通过以下XQL代码调用XSLT把TEI XML渲染成HTML:
xquery version "3.1"; declare namespace tei="http://www.tei-c.org/ns/1.0"; declare namespace m = "http://www.minorworksoflydgate.net/model"; declare default element namespace "http://www.w3.org/1999/xhtml"; declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization"; declare option output:method "xhtml"; declare option output:media-type "application/xhtml+xml"; declare option output:omit-xml-declaration "no"; declare option output:html-version "5.0"; declare option output:indent "no"; declare option output:include-content-type "no"; declare variable $exist:root as xs:string := request:get-parameter("exist:root", "xmldb:exist:///db/apps"); declare variable $exist:controller as xs:string := request:get-parameter("exist:controller", "/mwjl-app"); declare variable $text := request:get-data(); (:this variable allows the pipeline to work:) let $xsl := xs:anyURI($exist:root || $exist:controller || "/data/stylesheets/wrapper.xsl") return transform:transform($text, $xsl, ())
待转换的TEI XML主体是嵌套列表结构:
<list type="index"> <item n="draft" xml:id="6561"><emph rend="italic">A lamentacioun of our lady Maria</emph> <ref target="http://www.dimev.net/record.php?recID=6561">(DIMEV: 6561)</ref> </item> <list> <item> <ref target="/Quis_Dabit/Jesus_College_Q_G_8/Jesus_Q_G_8_f19v.html">Cambridge, Jesus College Q.G.8</ref> </item> <item><ref target="/Quis_Dabit/British_Library_Harley_2251/British_Library_Harley_2251_f42v.html" >London, British Library Harley 2251</ref></item> <item><ref target="/Quis_Dabit/British_Library_Harley_2255/British_Library_Harley_2255_f66v.html" >London, British Library Harley 2255</ref></item> <item><ref target="/Quis_Dabit/Laud_683/Laud_683_f78r.html">Oxford, Bodleian Library Laud misc. 683</ref></item> <item><ref target="/Quis_Dabit/St_John_56/St_John_56_73v.html">Oxford, St. John's College 56</ref></item> </list> <item n="draft" xml:id="747"><emph rend="italic">A Mumming at Eltham</emph><ref target="http://www.dimev.net/record.php?recID=747"> (DIMEV: 747)</ref></item> <list> <item><ref target="/Mumming_Eltham/Trinity_R_3_20/Trinity_R_3_20_f19r.html" >Cambridge, Trinity College R.3.20</ref></item> <item><ref target="/Mumming_Eltham/British_Library_Additional_29729/Add_29729_f135v.html" >London, British Library Addit. 29729</ref></item> </list> </list>
当前转换功能正常,但XML行数超过8000时,页面渲染速度明显变慢,远不如直接用Saxon转换的效率。因为是单XML页面,索引优化效果不好。我怀疑问题出在大量list/item组合的迭代处理,但不确定解决方法,想请教:
- 如何优化XQL以提升页面渲染速度?
- 是否应该放弃使用eXist-db?
补充:相关XSLT代码片段(wrapper.xsl和body.xsl):
wrapper.xsl:
<xsl:stylesheet xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:teix="http://www.tei-c.org/ns/Examples" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:rng="http://relaxng.org/ns/structure/1.0" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#default html a fo rng tei teix" version="3.0"> <xsl:include href="header.xsl"/> <xsl:include href="body.xsl"/> </xsl:stylesheet>
body.xsl核心片段:
<xsl:template match="tei:list"> <xsl:choose> <xsl:when test="@rend='ordered'"> <ol> <xsl:apply-templates/> </ol> </xsl:when> <xsl:when test="@type='index'"> <ul class="index"> <xsl:apply-templates/> </ul> </xsl:when> <xsl:when test="@type='simple'"> <ul class="nodisplay"> <xsl:apply-templates/> </ul> </xsl:when> <xsl:when test="@xml:id='compare'"> <ul class="nodisplay"> <xsl:apply-templates/> </ul> </xsl:when> <xsl:when test="@type='bibliography'"> <ul class="nodisplay bibliography"> <xsl:apply-templates/> </ul> </xsl:when> <xsl:otherwise> <ul> <xsl:apply-templates/> </ul> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="tei:list[@xml:id = 'bullet_list']/tei:item"> <li> <xsl:attribute name="class"> <xsl:text>bullet_list</xsl:text> </xsl:attribute> <xsl:apply-templates/> </li> </xsl:template> <xsl:template match="tei:item"> <xsl:choose> <xsl:when test="@xml:id"> <li> <a> <xsl:attribute name="name"> <xsl:value-of select="@xml:id"/> </xsl:attribute> <xsl:attribute name="class"> <xsl:text>anchor</xsl:text> </xsl:attribute> <xsl:apply-templates/> </a> </li> </xsl:when> <xsl:otherwise> <li> <xsl:apply-templates/> </li> </xsl:otherwise> </xsl:choose> </xsl:template>
优化建议与决策参考
一、XQL与XSLT层面的优化
1. 重构XSLT模板匹配逻辑
当前tei:list和tei:item模板依赖大量<xsl:choose>分支判断,针对大文档可优化为精准匹配的独立模板,减少运行时条件判断开销:
- 拆分
tei:list模板:<!-- 替换原tei:list模板 --> <xsl:template match="tei:list[@rend='ordered']"> <ol><xsl:apply-templates/></ol> </xsl:template> <xsl:template match="tei:list[@type='index']"> <ul class="index"><xsl:apply-templates/></ul> </xsl:template> <xsl:template match="tei:list[@type='simple'] | tei:list[@xml:id='compare']"> <ul class="nodisplay"><xsl:apply-templates/></ul> </xsl:template> <xsl:template match="tei:list[@type='bibliography']"> <ul class="nodisplay bibliography"><xsl:apply-templates/></ul> </xsl:template> <xsl:template match="tei:list"> <ul><xsl:apply-templates/></ul> </xsl:template> - 拆分
tei:item模板并使用属性值模板简化代码:
属性值模板替代<xsl:template match="tei:item[@xml:id]"> <li> <a name="{@xml:id}" class="anchor"> <xsl:apply-templates/> </a> </li> </xsl:template> <xsl:template match="tei:item"> <li><xsl:apply-templates/></li> </xsl:template><xsl:attribute>,既简化代码也提升处理器执行效率。
2. 优化eXist的XML读取方式
避免用request:get-data()读取原始XML字符串再二次解析,直接从数据库读取已解析的XML节点:
let $text := doc("/db/apps/mwjl-app/data/your-large-tei.xml")
跳过字符串转XML的解析步骤,节省资源开销。
3. 减少序列化冗余
将XQL中的output:omit-xml-declaration改为yes,减少大文档序列化时的额外处理(已设置output:indent="no"可保留)。
二、eXist-db配置优化
1. 调整JVM内存参数
eXist基于JVM运行,大文档处理需要足够堆内存。修改conf.xml中的JVM参数:
<java classname="org.exist.start.Main" fork="true"> <jvmarg value="-Xms4G"/> <jvmarg value="-Xmx8G"/> </java>
根据服务器配置调整堆大小,避免频繁GC拖慢处理速度。
2. 替换为Saxon作为XSLT处理器
eXist默认内置处理器性能弱于Saxon,可配置使用Saxon对齐本地测试性能:
- 将Saxon的jar包放入eXist的
lib/user目录; - 修改
conf.xml中的处理器配置:<transformer class="net.sf.saxon.TransformerFactoryImpl"/>
三、是否放弃eXist-db?
优先尝试上述优化,若仍无法达标再考虑替代方案:
- 若仅需TEI转HTML且文档静态,可采用静态生成:本地用Saxon批量转换后用普通Web服务器托管,性能最优;
- 若需动态查询、编辑TEI文档,eXist仍是适配的XML数据库,需确保配置和代码完成针对性优化;
- 替代选项可考虑BaseX等其他XML数据库,或用Python/Java编写自定义服务结合Saxon与数据库存储。
内容的提问来源于stack exchange,提问作者medievalmatt
相关产品推荐
相关产品推荐

