此时我已经获得了一个 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>
XSLT 用于在输入 XML 上进行转换
<?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>