我用XSLT 1.0已经几年了,并认为自己对这门语言已相当精通。但是有时候,我仍然会遇到一些问题。就在去年,我就遇到两件需要我进行例外处理的事情。
代码列表A与列表B为两个单独的文件,包括可下载的压缩文件中。
问题1
第一个问题与用XSLT从xml中生成SQL有关。该项目只需简单应用一个包含下列输出语句的样式表就足以开始:
<xsl:output method="text" indent="yes" media-type="text/sql"/>
不幸地是,那是开发过程的最高潮;从那里它就会下跌。哦,当然我生成了SQL,但它有一个特别麻烦的错误,即包含在文本中的省略符号。由于SQL使用省略符号来包围文本字符串,在字符串中遇到一个省略符号就成为大问题。另外就是省略符号是英尺的常见缩写,还有就是那里还使用了O'Connell、O'Connell和Paddy O'urniture这些名称,因此问题的规模变得更大。
初一看来,解决这一问题的最简单方法是用两个省略符号来代替每个单独的省略符号,它会告诉SQL字符串包含省略符号这一事实。可惜的是,因为XSLT使用省略符号作为分隔符,那个解决方案使问题越来越大。
遇到了这个问题不久,就像一道闪电,我们记起了“'”实体和类似下面的代码:
<xsl:choose>
?lt;xsl:when test="contains($string,')">
<!---->
?lt;/xsl:when>
?lt;xsl:otherwise>
<!---->
?lt;/xsl:otherwise>
</xsl:choose>
由于'被解释成一个单独的省略符号,上面的代码在样式表中生成一个错误。于是我又试用下面的代码:
<xsl:choose>
?lt;xsl:when test="contains($string,''')">
<!---->
?lt;/xsl:when>
?lt;xsl:otherwise>
<!---->
?lt;/xsl:otherwise>
</xsl:choose>
两段代码得到的结果几乎一样,只是现在有三个省略符号,而不是一个。这几乎包含了处理XSLT中省略符号时的常见错误。但是,还有更多的错误,包括外来物以及“不会出现错误但也无法工作”类型。不用描述每个错误,我们来了解什么在起作用吧:
<xsl:variable name="apostrophe">'</xsl:variable>
<xsl:choose>
?lt;xsl:when test="contains($string,$apostrophe)">
<!---->
?lt;/xsl:when>
?lt;xsl:otherwise>
<!---->
?lt;/xsl:otherwise>
</xsl:choose>
由于XSLT处理器处理变量的方式与处理文字的方式不同,我们可以根据自己的利益来使用这一点。利用这方面的知识,我编写了下面的命名模板,在参数字符串中使用此模板用两个省略符号代替单独的省略符号,有趣的是,参数字符串叫做string。另外,因为这个模板是回归型的,它可以处理单个省略符号的多个事件,如列表A所示。
列表A——splApostrophe模板
<!--
?Template: sqlApostrophe
?Mode: n/a
?Parameter(s): string [required].
?Description:?Parses the parameter (string)
replacing
single apostrophes (')
with two apostrophes ('').
?This prevents issues in the output SQL.
-->
<xsl:template name="sqlApostrophe">
?lt;xsl:param name="string"/>
?lt;xsl:variable name="apostrophe">'</xsl:variable>
?lt;xsl:choose>
<xsl:when
test="contains($string,$apostrophe)">
<xsl:value-of select=
"concat(substring-before($string,$apostrophe),
$apostrophe,$apostrophe)"
disable-output-escaping="yes"/>
<xsl:call-template name="sqlApostrophe">
<xsl:with-param name="string"
select="substring-after($string,$apostrophe)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"
disable-output-escaping="yes"/>
</xsl:otherwise>
?lt;/xsl:choose>
</xsl:template>
问题2
去年让我生气的第二个问题更多与嫉妒有关。我本以为我在缓解中,不幸的是,在SQL与XSLT间来回证明我是错的。我知道,在SQL中有一个我认为可以为工具箱增加重大价值的特性,SQL IN子句的XSLT对应特性。
如果你不熟悉IN子句,它就像一个条件语句,它对某一个特定的行进行测试,看里面是否包含以逗号隔开的列表中的一个值。发现这个值时,结果为真;没有发现这个值,则结果为假。列表B中的XSLT代码即可完成这一工作。
列表B——IN模板
<!?br>?Template: in
?Mode: n/a
?Parameter(s): list [required].
?Value [required].
?Description:?Determines if value is IN a list of values.
-->
<xsl:template name="in">
?<xsl:param name="list"/>
?<xsl:param name="value"/>
?<xsl:choose>
?<xsl:when test="$list =
$value">true</xsl:when>
?<xsl:when test="substring-before($list,',') =
$value">true</xsl:when>
?<xsl:when test="string-length($list) = 0">false</xsl:when>
?<xsl:otherwise>
?<xsl:call-template name="in">
?<xsl:with-param name="list" select="substring-after($list,',')"/>
?<xsl:with-param name="value" select="$value"/>
?</xsl:call-template>
?</xsl:otherwise>
?</xsl:choose>
</xsl:template>
不会伤害感情
这些事件指出,在有工作要做时,生气并不是一个好的选择。与将自己的沮丧发泄在果菲身上的唐纳德不同,当我感到沮丧时,我努力变得更有创造性,将沮丧发泄在软件上。在这种情况下,是Altova的XMLSpy。幸运的是,它与果菲不同,它的感情不会受到伤害。
责任编辑:张琎