与Velocity等其他模板引擎类似的模板成语?

时间:2012-11-27 18:02:21

标签: templates xslt velocity

我有一个XSLT(2.0)文件;它接受输入XML数据文件并创建DDL / SQL语句。 它工作得很好。但是它有点难以维护,因为它在'concat'语句中包含了很多格式化信息,如下所示:

<xsl:value-of select="concat('CREATE USER ',$username,' IDENTIFIED BY ',$password,';',$nl)"/>

我更喜欢做的是以这样的方式编码我的SQL语句:

<some-enclosing-elements>[...]CREATE USER <username/>, identified by <password/>; [literally a newline here][...]</some-enclosing-elements>

我可能会将这种格式保存在XML数据文件本身的XSLT或数据文档的顶部的“查找”表中(我还无法解决)。

是否有允许这种模板的标准习语? 有什么想法吗?

顺便说一下;当然,数据文档包含许多不同的用户

2 个答案:

答案 0 :(得分:2)

AVT方法对我的品味有点过于狡猾。我倾向于依赖xsl:value-of:

完成的隐式连接(在2.0中)
<xsl:value-of select="'CREATE USER', $username, 'identified by', $password"/>

我在这种文本模板很重要的应用程序中使用的另一种方法是在XSLT中基本上编写自己的模板引擎;有一个“消息文件”,其中包含

形式的消息模板
<message nr="1">CREATE USER <p:user/> IDENTIFIED BY <p:password/></message>

然后编写模板规则以通过替换参数来扩展消息。

答案 1 :(得分:1)

@xiaoyi是对的,显示了使用concat()的主要替代方案。然而,由于你必须不断重复concat(),这比<xsl:value-of select="..." />更加重要。

一个不错的选择是使用attribute value templates(AVTs):

[...]CREATE USER {username}, identified by {password};
[...]

但ATV仅适用于(某些)属性,不适用于文本节点(直接)。你如何将它们用于此目的?

XSLT 2.0的一种方法是使用AVT创建一个带有属性的新文字结果元素;使用AVT指定该属性的值;然后选择新属性的值:

<xsl:variable name="query">
  <dummy val="[...]CREATE USER {username}, identified by {password};
[...]" />
</xsl:variable>
<xsl:value-of select="$query//@val" />

是的,每个格式化字符串有一些显着的开销,但字符串中每个字段的开销非常小。你可以像这样一起做几个字符串:

<xsl:variable name="queries">
  <q val="[...]CREATE USER {username}, identified by {password}; &#10;[...]" />
  <q val="[...]CREATE TABLE {tablename}, blah blah; &#10;[...]" />
</xsl:variable>
<xsl:value-of select="$queries/q[1]/@val" />
<xsl:value-of select="$queries/q[2]/@val" />

您可以使用上述位置索引,或使用id属性来标识每个字符串。

我没有看到其他地方提倡的这种方法,所以我很想知道其他人对此的看法。

没关系,除了......

考虑到迈克尔凯的答案所显示的更简单的方法,我认为这样做没有任何意义。我想这可以解释为什么其他人没有提倡这种方法。 : - )

我能想到这种方法可能仍然有用的唯一情况是,如果你不能使用XSLT 2.0,但你可以访问nodeset()扩展功能(例如在IE或.NET环境中) )。在这种情况下,您需要在nodeset( )之前的XPath表达式中将$queries包裹在/左右。