Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xslt 使用xsl:call-template优化转换模板(使用外部XML)_Xslt_Xslt 2.0 - Fatal编程技术网

Xslt 使用xsl:call-template优化转换模板(使用外部XML)

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模板中实现这一点 任何

此时,我已经得到了一个XSLT(从现在起名为myLookupTable.XSLT),它可以包含在其他XSLT文件中,以便能够进行一些代码转换。这个myLookupTable.xslt是一个命名模板,每个人都可以使用它来编写xslt文件并使用它。所以我真的需要像现在一样坚持使用这个
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))))