Optimization 优化<;xsl:choose>;有很多<;xsl:when>;
我有一系列中型XML文档,主要是文本,有几个节点表示要扩展的宏,例如:Optimization 优化<;xsl:choose>;有很多<;xsl:when>;,optimization,xslt,Optimization,Xslt,我有一系列中型XML文档,主要是文本,有几个节点表示要扩展的宏,例如: <foo>Some text <macro>A1</macro> ... <macro>B2</macro> ...etc...</foo> 一些文本A1。。。B2……等等。。。 我的目标是用相应的XML替换每个宏。通常它是一个带有不同属性的标记,但也可以是其他HTML 样式表是通过编程生成的,其中一种方法是为每个宏创建一个模板,例如 <xsl
<foo>Some text <macro>A1</macro> ... <macro>B2</macro> ...etc...</foo>
一些文本A1。。。B2……等等。。。
我的目标是用相应的XML替换每个宏。通常它是一个带有不同属性的
标记,但也可以是其他HTML
样式表是通过编程生成的,其中一种方法是为每个宏创建一个模板,例如
<xsl:template match="macro[.='A1']">
<!-- content goes here -->
</xsl:template>
<xsl:template match="macro[.='A2']">
<!-- other content goes here -->
</xsl:template>
<xsl:template match="macro[.='B2']">
<!-- etc... -->
</xsl:template>
它工作得很好,但它最多可以有100个宏,而且性能不太好(我使用的是libxslt)。我尝试了几种替代方法,例如:
<xsl:template match="macro">
<xsl:choose>
<xsl:when test=".='A1'">
<!-- content goes here -->
</xsl:when>
<xsl:when test=".='A2'">
<!-- other content goes here -->
</xsl:when>
<xsl:when test=".='B2'">
<!-- etc... -->
</xsl:when>
</xsl:choose>
</xsl:template>
它的性能稍微好一点。我已尝试添加另一级别的分支,例如:
<xsl:template match="macro">
<xsl:choose>
<xsl:when test="substring(.,1,1) = 'A'">
<xsl:choose>
<xsl:when test=".='A1'">
<!-- content goes here -->
</xsl:when>
<xsl:when test=".='A2'">
<!-- other content goes here -->
</xsl:when>
</xsl:choose>
</xsl:when>
<xsl:when test=".='B2'">
<!-- etc... -->
</xsl:when>
</xsl:choose>
</xsl:template>
它的加载速度稍慢(XSL更大,更复杂),但执行速度稍快(每个分支可以消除几种情况)
现在我想知道,有没有更好的方法?我有大约50-100个宏。通常,转换是使用libxslt执行的,但我不能使用其他XSLT引擎的专有扩展
欢迎任何输入:)如果您的宏是固定的XML,您可以有一个类似以下内容的
macros.XML
文档:
<?xml version="1.0"?>
<macros>
<macro name="A1"><!-- content goes here --></macro>
<macro name="A2"><!-- content goes here --></macro>
</macros>
然后,您可以拥有:
<xsl:template match="macro">
<xsl:variable name="name" select="text()"/>
<xsl:apply-templates select="document(macros.xml)/macros/macro[@name=$name]" mode="copy"/>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy><xsl:copy-of select="*"/>
<xsl:apply-templates mode="copy"/>
</xsl:copy>
</xsl:template>
这会提高性能吗?如果您的宏是固定的XML,则可以使用类似以下内容的
macros.XML
文档:
<?xml version="1.0"?>
<macros>
<macro name="A1"><!-- content goes here --></macro>
<macro name="A2"><!-- content goes here --></macro>
</macros>
然后,您可以拥有:
<xsl:template match="macro">
<xsl:variable name="name" select="text()"/>
<xsl:apply-templates select="document(macros.xml)/macros/macro[@name=$name]" mode="copy"/>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy><xsl:copy-of select="*"/>
<xsl:apply-templates mode="copy"/>
</xsl:copy>
</xsl:template>
这是否提高了性能?尝试将所有的
宏
处理提取到一个单独的模板模式中,并仅对宏
元素的内容运行它。即:
<xsl:template match="macro">
<xsl:apply-templates mode="macro"/>
</xsl:template>
<xsl:temlate match="text()[. = 'A1']" mode="macro">
...
</xsl:template>
...
我怀疑您的情况会变慢,因为您的规则会针对输入中的每个节点逐一进行检查。这样,您就可以进行一次检查,查看它是否是一个
宏
,并且只有当它是时,内容才会进一步匹配。尝试将所有宏
处理提取到一个单独的模板模式中,并且只对宏
元素的内容运行它。即:
<xsl:template match="macro">
<xsl:apply-templates mode="macro"/>
</xsl:template>
<xsl:temlate match="text()[. = 'A1']" mode="macro">
...
</xsl:template>
...
我怀疑您的情况会变慢,因为您的规则会针对输入中的每个节点逐一进行检查。通过这种方式,您可以进行一次检查,查看它是否是一个
宏,并且只有当它是宏时,内容才会进一步匹配。这将是另一种方式:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:variable name="dummy">
<mac id="A1">success</mac>
<mac id="A2">fail</mac>
<mac id="B1">This <b>fail</b></mac>
<mac id="B2">This <b>success</b></mac>
</xsl:variable>
<xsl:key name="macro" match="mac" use="@id"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="macro">
<xsl:variable name="me" select="."/>
<xsl:for-each select="document('')">
<xsl:copy-of select="key('macro',$me)/node()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
成功
失败
这次失败了
这一成功
注意:这就是性能:XML解析1805ms,XSL解析0483ms,转换0215ms这是另一种方式:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:variable name="dummy">
<mac id="A1">success</mac>
<mac id="A2">fail</mac>
<mac id="B1">This <b>fail</b></mac>
<mac id="B2">This <b>success</b></mac>
</xsl:variable>
<xsl:key name="macro" match="mac" use="@id"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="macro">
<xsl:variable name="me" select="."/>
<xsl:for-each select="document('')">
<xsl:copy-of select="key('macro',$me)/node()"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
成功
失败
这次失败了
这一成功
注意:这就是性能:XML解析1805ms,XSL解析0483ms,转换0215ms我尝试过
,但性能更差,考虑到它必须访问外部资源并在其上运行一些XPath,这是可以预料的。也许我可以在某个地方用xsl:key再试一次。。。谢谢:)您尝试过将文档加载到变量中并使用它吗?不过,您需要使用扩展来支持变量作为节点集。这将只加载文档一次。我尝试过
,但性能更差,考虑到它必须访问外部资源并在其上运行一些XPath,这是意料之中的。也许我可以在某个地方用xsl:key再试一次。。。谢谢:)您尝试过将文档加载到变量中并使用它吗?不过,您需要使用扩展来支持变量作为节点集。这将只加载一次文档。这种方法的性能与我的第一种方法大致相同,但由于额外的
,会有一点损失。不管怎样,它实际上并不慢,或者至少不比XSL转换预期的慢。libxslt做得不错,我只是想看看是否可以从中挤出更多的性能。这种方法的性能与我的第一种方法大致相同,但由于额外的
,会有一点损失。不管怎样,它实际上并不慢,或者至少不比XSL转换预期的慢。libxslt做得不错,我只是想看看是否可以从中获得更高的性能。奇怪的是,我已经尝试过类似的方法,但没有成功,因为document(“”)
返回的是源文档的根,而不是样式表的根。我刚刚检查了XSLT规范,事实上,它应该返回样式表的根,这样要么我发现了一个bug,要么我把事情搞砸了。我会再试一次,并保持更新,谢谢。确实,这是一个已知的LIbxSLT错误,我打了()我让它工作,但性能似乎与我列出的第二种方法一致。如果重复使用同一个宏,它的伸缩性似乎更好。奇怪的是,我已经尝试过类似的方法,但没有成功,因为document(“”)
返回的是源文档的根,而不是样式表的根。我刚刚检查了XSLT规范,事实上,它应该返回样式表的根,这样要么我发现了一个bug,要么我把事情搞砸了。我会再试一次,让你随时了解最新情况,谢谢。的确,这是一个好主意