我有一个参数化的,可重复的XML片段,我在整个XSLT(2.0)中引用它。它采用以分号分隔的字符串,我将其标记并循环以生成每个子元素。例如,字符串USNY;UKLN
将产生:
<businessCenters>
<businessCenter>USNY</businessCenter>
<businessCenter>UKLN</businessCenter>
</businessCenters>
每次我希望产生这种情况时,可以直接使用for-each,但是我希望通过功能或类似功能对其进行模块化。
有了谷歌,我觉得功能是错误的做法,因为我没有返回一个值,只是希望在节点处就地处理字符串。因此,命名模板看起来可能是执行此操作的正确方法,并为字符串传入参数。这link似乎表明我正在走上正轨。
<xsl:template name="business-centers">
<xsl:param name="centers" as="xs:string"/>
<businessCenters>
<xsl:for-each select="tokenize($centers,';')">
<businessCenter>
<xsl:value-of select="."/>
</businessCenter>
</xsl:for-each>
</businessCenters>
</xsl:template>
可以像这样调用:
<xsl:call-template name="business-centers">
<xsl:with-param name="centers" select="myns:get_centers($foo)"/>
</xsl:call-template>
这似乎有效。不过我的问题是 - 这是正确的方法吗?
我是否正确地假设没有一种敏感的方法来执行此功能?
我也是正确的假设尽管建议似乎更像是一般规则而不是通过调用模板 - 而不是调用模板 - 这里也没有合理的方法(按照difference between <xsl:apply-template> and <xsl:call-template>?)?
更新
所以按照以下@ martin-honnen的建议 - 似乎不是使用函数作为生成XML的副作用,我可以像这样返回生成的XML。我没有意识到函数的整个主体的(结果)被返回 - 非常整洁。
注意我没有指定退货类型?这是正常的吗?
<xsl:function name="qt:business-centers">
<xsl:param name="centers" as="xs:string"/>
<businessCenters>
<xsl:for-each select="tokenize($centers,';')">
<businessCenter>
<xsl:value-of select="."/>
</businessCenter>
</xsl:for-each>
</businessCenters>
</xsl:function>
鉴于此,我想我唯一的突出问题是 - 我是否正确地假设使用该函数或命名模板只不过是一个人格问题?或者是否有技术上的理由选择其中一种?
答案 0 :(得分:3)
您可能需要解释您使用Google找到的文档以及您解释的文档的哪一段,如您所说,某个功能不起作用。如果你将你在该命名模板中的代码填充到一个函数中并用例如<xsl:sequence select="mf:business-centers(myns:get_centers($foo))"/>
,它与命名模板一样,返回businessCenters
元素节点。因此,功能使用非常精细。
至于使用apply-templates
,您可以在XSLT 3中使用例如<businessCenters>
<xsl:apply-templates select="tokenize($centers,';')"/>
</businessCenters>
<xsl:template match=".[. instance of xs:string]" expand-text="yes">
<businessCenter>{.}</businessCenter>
</xsl:template>
。
git log -5
XSLT 2不允许您编写匹配原始值(如字符串)的模板。
答案 1 :(得分:1)
我经常发现当结果是原子值时使用函数更方便,而当结果是节点树时命名模板(或模板规则),但这纯粹是一种方便和惯例:函数和模板都可以无限制地返回任何XDM值。函数和模板之间的区别在于它们的调用方式,而不是它们可以执行的操作。