Xslt 使用xsl:call-template优化转换模板(使用外部XML)
此时,我已经得到了一个XSLT(从现在起名为myLookupTable.XSLT),它可以包含在其他XSLT文件中,以便能够进行一些代码转换。这个myLookupTable.xslt是一个命名模板,每个人都可以使用它来编写xslt文件并使用它。所以我真的需要像现在一样坚持使用这个Xslt 使用xsl:call-template优化转换模板(使用外部XML),xslt,xslt-2.0,Xslt,Xslt 2.0,此时,我已经得到了一个XSLT(从现在起名为myLookupTable.XSLT),它可以包含在其他XSLT文件中,以便能够进行一些代码转换。这个myLookupTable.xslt是一个命名模板,每个人都可以使用它来编写xslt文件并使用它。所以我真的需要像现在一样坚持使用这个xsl:call模板 XSLT目前运行良好,但是对于包含转换的真正大的XML文件,它需要花费更多的时间,我正在研究如何优化 例如: 使用xsl:key更好吗?如果是这样,我将如何在xsl:call模板中实现这一点 任何
xsl:call模板
XSLT目前运行良好,但是对于包含转换的真正大的XML文件,它需要花费更多的时间,我正在研究如何优化
例如:
- 使用
xsl:key
更好吗?如果是这样,我将如何在xsl:call模板中实现这一点
- 任何其他结构更改,以便我仍然能够坚持使用
xsl:call模板
- 如果最好去掉
xsl:call模板
,我为什么要这样做?我如何让其他人尽可能容易地实现它
我读过一篇文章,我明白了这一点,但不确定如何在这个xsl:call-template
示例中实现这一点
感谢您的帮助和建议
输入XML示例
<?xml version="1.0" encoding="UTF-8"?>
<pref:data xmlns:pref="http://example.org/uri/data">
<pref:PackageGroup>
<pref:sendPackage>BX</pref:sendPackage>
<pref:sendRelation>66778899</pref:sendRelation>
</pref:PackageGroup>
<pref:TypeGroup>
<pref:sendType>80</pref:sendType>
<pref:sendRelation>88996677</pref:sendRelation>
</pref:TypeGroup>
</pref:data>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:conv="http://example.org/uri/lookuptable">
<xsl:template name="myLookup">
<xsl:param name="file"/><!-- Name of the conversion XML file -->
<xsl:param name="direction"/><!-- 'in' ('directionIncoming' element is used) or 'out' ('directionOutgoing' element is used) -->
<xsl:param name="function"/><!-- 'copy', 'copy+', 'filter', 'filter+' -->
<xsl:param name="table"/><!-- Name of the lookup table to use for conversion (see 'name' attribute of 'translateCode' element) -->
<xsl:param name="relation"/><!-- Relation number to use for conversion (see 'relation' attribute of 'translateValue' element) -->
<xsl:param name="value"/><!-- Value to convert -->
<xsl:variable name="fallbackRelation">0</xsl:variable>
<!-- Step 1: convert input value -->
<xsl:variable name="result1">
<xsl:call-template name="convert">
<xsl:with-param name="file" select="$file"/>
<xsl:with-param name="direction" select="$direction"/>
<xsl:with-param name="function" select="$function"/>
<xsl:with-param name="table" select="$table"/>
<xsl:with-param name="relation" select="$relation"/>
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
</xsl:variable>
<!-- Step 2: if result is empty and function name ends with '+' convert again using fallback relation number -->
<xsl:variable name="result2">
<xsl:choose>
<xsl:when test="string-length($result1)=0 and ends-with($function,'+') and $relation!='0'">
<xsl:call-template name="convert">
<xsl:with-param name="file" select="$file"/>
<xsl:with-param name="direction" select="$direction"/>
<xsl:with-param name="function" select="$function"/>
<xsl:with-param name="table" select="$table"/>
<xsl:with-param name="relation" select="$fallbackRelation"/>
<xsl:with-param name="value" select="$value"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$result1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Step 3: if result is still empty and function name starts with 'copy' use original input value as output result -->
<xsl:variable name="result3">
<xsl:choose>
<xsl:when test="string-length($result2)=0 and starts-with($function,'copy')">
<xsl:value-of select="$value"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$result2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Step 4: final conversion result -->
<xsl:value-of select="$result3"/>
</xsl:template>
<!-- Template for actual conversion using external conversion XML file. -->
<xsl:template name="convert">
<xsl:param name="file"/>
<xsl:param name="direction"/>
<xsl:param name="function"/>
<xsl:param name="table"/>
<xsl:param name="relation"/>
<xsl:param name="value"/>
<xsl:variable name="result">
<xsl:choose>
<xsl:when test="$direction='in'">
<xsl:value-of select="document($file)/conv:myLookupTable/conv:table[@name=$table]/conv:directionIncoming/conv:translateCode[@name=$value]/conv:translateValue[@relation=$relation]/text()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="document($file)/conv:myLookupTable/conv:table[@name=$table]/conv:directionOutgoing/conv:translateCode[@name=$value]/conv:translateValue[@relation=$relation]/text()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$result"/>
</xsl:template>
</xsl:stylesheet>
您应该能够使用键替换表达式,例如document($file)/conv:myLookupTable/conv:table[@name=$table]
<xsl:key name="k1" match="conv:myLookupTable/conv:table" use="@name"/>
作为
现在是您定义的conv:directionIncoming/conv:translateCode[@name=$value]
<xsl:key name="k2" match="conv:directionIncoming/conv:translateCode" use="@name"/>
与
最后是
document($file)/conv:myLookupTable/conv:table[@name=$table]/conv:directionIncoming/conv:translateCode[@name=$value]/conv:translateValue[@relation=$relation]
你会用
<xsl:key name="k3" match="conv:translateCode/conv:translateValue" use="@relation"/>
我还建议尽量使用
而不是
,并使用
而不是
。在大多数情况下,这应该更有效。对大型输入文件使用xsl:key
,肯定会非常有用。我有过输入文件在800-1000兆字节范围内的案例,其中我经历了10-100倍的加速。我认为其中一个限制可能是关键定义必须是XSLT样式表标记的子项。这将要求您取消隐藏XML映射文件结构的一些细节。另一方面,myLookup
的一些参数可能不再是必需的,因为它们是在密钥定义中隐式给出的。相反,您必须传递密钥名称。感谢您提供完整和扩展的答案。不知道在xsl:with param
和xsl:variable
中使用select
属性也会更有效。非常感谢如何处理键索引中不存在的查找?例如,在输入XML将BX
更改为XX
@MarkVeenstra时,如果值不存在,基于键的查找是否会给出与以前代码不同的结果?与您可以检查类似,例如,..
如果需要,您可以检查..
。但是我没有看到你做这样的检查。我用我得到的错误更新了问题。我还尝试在它前面做一个xsl:if
。但我还是收到了错误,但测试通过了,真奇怪。我使用的输入和转换XML与本问题中发布的相同。看起来我应该按如下方式分别测试所有键:
。当我这样做时,错误消失了,它将返回一个空节点,这是正确的。
<xsl:key name="k1" match="conv:myLookupTable/conv:table" use="@name"/>
document($file)/conv:myLookupTable/conv:table[@name=$table]
key('k1', $table, document($file))
<xsl:key name="k2" match="conv:directionIncoming/conv:translateCode" use="@name"/>
document($file)/conv:myLookupTable/conv:table[@name=$table]/conv:directionIncoming/conv:translateCode[@name=$value]
key('k2', $value, key('k1', $table, document($file)))
document($file)/conv:myLookupTable/conv:table[@name=$table]/conv:directionIncoming/conv:translateCode[@name=$value]/conv:translateValue[@relation=$relation]
<xsl:key name="k3" match="conv:translateCode/conv:translateValue" use="@relation"/>
key('k3', $relation, key('k2', $value, key('k1', $table, document($file))))