我有几个XSLT转换。它们都包含相同的模板,看起来像这样(其实现和功能无关紧要):
<xsl:template match="firstField| secondField | thirdField">
<xsl:element name="{local-name(.)}">
<xsl:choose>
<xsl:when test="string-length(.)!=0"><xsl:value-of select="."/></xsl:when>
<xsl:otherwise>ABSENT</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
如您所见,我列出了要在模板匹配中应用的模板的字段。
但实际上,我想在所有转换中都使用此模板,但是当然要使用不同的字段名称。换句话说,我想像将其用作函数一样使用它,我可以将其插入任何.xsl文件并指定参数列表,这些参数是要通过这种方式修改的字段的名称。
我可以用XSLT做到吗?
更新,我可能误解了您的问题,并再次查看了您的模板(有关解决方案说明的更一般的描述,请参见下文)。
你写了:
<xsl:template match="firstField| secondField | thirdField"> <xsl:element name="{local-name(.)}"> <xsl:choose> <xsl:when test="string-length(.)!=0"><xsl:value-of select="."/></xsl:when> <xsl:otherwise>ABSENT</xsl:otherwise> </xsl:choose> </xsl:element> </xsl:template>
和:
我想像将其用作函数一样使用它,我可以将其插入任何.xsl文件并指定参数列表,这些参数是通过这种方式修改的字段的名称。
如果用“这样”的意思是说:
xsl:copy
就足够了)然后,您可以按照以下方式进行操作。但这仅在您的要求像您所说的那样普遍适用于您的用例时才有效。
编写如下模板:
<xsl:variable name="names">
<names>
<n>firstField</n>
<n>secondField</n>
<n>thirdField</n>
</names>
</xsl:variable>
<xsl:template match="*" mode="by-name">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="self::node()" mode="text" />
</xsl:element>
</xsl:template>
<xsl:template match="node()" mode="by-name" />
<xsl:template match="*[text()]" mode="text">
<xsl:copy />
</xsl:template>
<xsl:template match="*[not(text())]" mode="text">
<xsl:text>ABSENT</xsl:text>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="your/current/whatever" />
</xsl:template>
<xsl:template match="*">
<xsl:for-each select="exslt:node-set($names)/names/n/text()">
<xsl:apply-templates select="self::*[name() = .]" mode="by-name" />
</xsl:for-each>
</xsl:template>
将上面的代码放置在一个单独的文件中(变量除外),应将其放置在此处,但将其保留为空。使用xsl:import
导入此文件,你现在需要做的唯一事情是重写xsl:variable
。
在XSLT 2.0和3.0中,有比这更通用和更简单的方法,但是此版本可与XSLT 1.0一起使用。
免责声明:未经测试,可能包含错误,当然可以根据您的需要进行调整;)
是的,您可以这样做。不同的XSLT版本具有不同的抽象级别:
您可以创建一个命名模板(只需为其命名)。如果使用调用命名模板xsl:call-template
,则当前上下文项将用作模板内的上下文项。这将解决您的问题,其中包含模板匹配项中的字段名称。
您可以将其放置在单独的文件中,然后使用进行导入,使用xsl:import
可以在需要时覆盖它,或者使用xsl:include
不允许覆盖,并且在发生命名冲突时会引发错误。
您可以在XSLT 2.0中创建一个可以称为任何其他函数的函数。函数可以包含您上面显示的模板。
在XSLT 2.0中,您也可以使用导入和包含。
您可以执行与以前版本相同的操作,但是现在可以将它们放入(预编译)软件包中,这使得重用,重新分发和调用它们变得更加容易。
此外,XSLT 3.0在覆盖和接受/公开使用过的程序包的组件方面具有大大改进的系统。
您可能有一个当前使用的地方xsl:apply-templates
。如果要防止重复声明匹配项xsl:template
,可以通过创建泛型来解决此问题:
<xsl:template match="node()" mode="special">
<xsl:call-template name="yourNamedTemplate" />
</xsl:template>
然后使用以下方法“调用”该方法:
<xsl:apply-templates select="firstField | secondField | thirdField" mode="special" />
如果可重用性很重要,那么您的“库样式表”(在XSLT 3.0中会弹出官方术语“库包”),您应该在名称空间中指定模式的名称。实际上,可重用样式表中的任何命名组件(命名模板,模式,函数,累加器,键)都应位于其自己的命名空间中。这样可以防止冲突,如果用户要覆盖冲突,则必须明确地这样做。
您可以创建一个“继承链”。如果A导入B导入了C,则对A中的命名组件,然后是B,然后是C赋予最高优先级。对于冲突的匹配模板,也是如此。(通常)在主体样式表中(通常是这样)是不允许的(因此设置优先级),但是A可以与B或C具有相同的匹配模板。在这种情况下,A越过B越过C越好。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句