此时我已经有了一个XSLT(从现在起名为myLookupTable.xslt),它可以包含在其他XSLT文件中,以便能够进行一些代码转换。这个myLookupTable.xslt是一个命名模板,每个人都可以使用它来编写XSLT文件并想要使用它。所以我现在需要坚持这个xsl:call-template
。
XSLT目前工作正常,但是包含转换的非常大的XML文件花费了更多时间,我正在研究如何优化。
例如:
xsl:key
更好吗?如果是这样,我将如何在xsl:call-template
?xsl:call-template
?xsl:call-template
,我为什么要这样做呢?我怎样才能让其他人尽可能轻松地实现这个呢?我读过一篇关于Muenchian Method的文章,我明白了这一点,但不太确定如何在这个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上进行转换的XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pref="http://example.org/uri/data">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Include lookup table XSLT and add variable to the lookup table xml -->
<xsl:include href="myLookupTable.xslt"/>
<xsl:variable name="myLookupTableFile">myLookupTable.xml</xsl:variable>
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Translate packageCode -->
<xsl:template match="pref:sendPackage">
<xsl:copy>
<xsl:call-template name="myLookup">
<xsl:with-param name="file"><xsl:value-of select="$myLookupTableFile" /></xsl:with-param>
<xsl:with-param name="direction">in</xsl:with-param>
<xsl:with-param name="function">filter</xsl:with-param>
<xsl:with-param name="table">packageCode</xsl:with-param>
<xsl:with-param name="relation"><xsl:value-of select="following-sibling::pref:sendRelation"/></xsl:with-param>
<xsl:with-param name="value"><xsl:value-of select="."/></xsl:with-param>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<!-- Translate type -->
<xsl:template match="pref:sendType">
<xsl:copy>
<xsl:call-template name="myLookup">
<xsl:with-param name="file"><xsl:value-of select="$myLookupTableFile" /></xsl:with-param>
<xsl:with-param name="direction">in</xsl:with-param>
<xsl:with-param name="function">filter</xsl:with-param>
<xsl:with-param name="table">type</xsl:with-param>
<xsl:with-param name="relation"><xsl:value-of select="following-sibling::pref:sendRelation"/></xsl:with-param>
<xsl:with-param name="value"><xsl:value-of select="."/></xsl:with-param>
</xsl:call-template>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
包含xsl:call-template
的XSLT<?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>
可用于查找代码转换的XML
<?xml version="1.0" encoding="UTF-8"?>
<myLookupTable xmlns="http://example.org/uri/lookuptable">
<table name="packageCode">
<directionIncoming>
<translateCode name="BX">
<translateValue relation="99887766">GH</translateValue>
<translateValue relation="66778899">LK</translateValue>
<translateValue relation="88996677">LK</translateValue>
</translateCode>
<translateCode name="PL">
<translateValue relation="99887766">BT</translateValue>
<translateValue relation="66778899">LK</translateValue>
<translateValue relation="88996677">LK</translateValue>
</translateCode>
</directionIncoming>
<directionOutgoing>
<translateCode name="LK">
<translateValue relation="66778899">BX</translateValue>
<translateValue relation="88996677">BX</translateValue>
</translateCode>
<translateCode name="BT">
<translateValue relation="99887766">PL</translateValue>
</translateCode>
<translateCode name="GH">
<translateValue relation="99887766">PL</translateValue>
</translateCode>
</directionOutgoing>
</table>
<table name="type">
<directionIncoming>
<translateCode name="10">
<translateValue relation="99887766">20</translateValue>
<translateValue relation="66778899">30</translateValue>
<translateValue relation="88996677">30</translateValue>
</translateCode>
<translateCode name="80">
<translateValue relation="99887766">90</translateValue>
<translateValue relation="66778899">30</translateValue>
<translateValue relation="88996677">30</translateValue>
</translateCode>
</directionIncoming>
<directionOutgoing>
<translateCode name="30">
<translateValue relation="66778899">10</translateValue>
<translateValue relation="88996677">10</translateValue>
</translateCode>
<translateCode name="90">
<translateValue relation="99887766">80</translateValue>
</translateCode>
<translateCode name="20">
<translateValue relation="99887766">80</translateValue>
</translateCode>
</directionOutgoing>
</table>
</myLookupTable>
修改
当我按照下面的描述应用Martin Honnen他的解决方案时,我将输入XML从<pref:sendPackage>BX</pref:sendPackage>
更改为<pref:sendPackage>XX</pref:sendPackage>
(键查找将不返回任何内容)并且我在Altova XML Spy中执行转换我得到了错误:
代码如下所示:
<xsl:value-of select="key('relationKey', $relation, key('incomingKey', $value, key('tableKey', $table, document($file))))/text()" />
即使我在它周围做xsl:if
,测试也会通过(足够奇怪),但xsl:value-of select
仍然会出现同样的错误:
<xsl:if test="normalize-space(key('k3', $relation, key('k2', $value, key('k1', $table, document($file))))/text()) != ''">
<xsl:value-of select="key('k3', $relation, key('k2', $value, key('k1', $table, document($file))))/text()" />
</xsl:if>
答案 0 :(得分:1)
您应该能够使用键来替换document($file)/conv:myLookupTable/conv:table[@name=$table]
之类的表达式,例如
<xsl:key name="k1" match="conv:myLookupTable/conv:table" use="@name"/>
允许你重写
document($file)/conv:myLookupTable/conv:table[@name=$table]
as
key('k1', $table, document($file))
现在为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]
与
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))))
我还建议尽可能使用<xsl:with-param name="param-name" select="foo"/>
代替<xsl:with-param name="param-name"><xsl:value-of select="foo"/></xsl:with-param>
,并使用<xsl:variable name="var-name" select="foo"/>
代替<xsl:variable name="var-name"><xsl:value-of select="foo"/></xsl:variable>
。在大多数情况下,这应该更有效。