在通过编程实现效率非常低或者无法实现的情况下,查找表是一种常用的快速搜索技术。查找表由联系键和值的映射组成。 那篇文章展示了如何用 XSLT 构造查找表,但没有涉及以下两个技术细节:如何处理查找表中没有发现的键,或者如何提供默认值。阅读本文之前,您可以先看一看那篇文章。
查找错误
上一篇文章中,源代码清单中的州缩写名恰好都在查找表中。但是如果使用伪造的州缩写名来调用转换,又会怎么样呢,比如 ZZ。下面的片段取自上一篇文章中的实际查找代码:
<xsl:value-of select="key('state-lookup', $curr-label/address/state)/s:name"/>
如果 $curr-label 是 ZZ,就无法在 state-lookup 键中找到值, key 函数调用的结果是一个空节点集, xsl:value-of 指令将其转化为一个空字符串。对于您来说,也许这其中就有足够多的错误,但也可能不是错误。比如,如果从查找表某个值得到空字符串是合法的,就无法和错误区分开。报告查找错误最简单(而且不会出错)的办法是检查 key 函数返回的节点集是否为空,然后生成一个 xsl:message 元素并赋予属性 terminate="yes"。清单 1 是一个完整的例子,它以上一篇文章中的样式表内查找技术为基础,增加了错误通知技术。
清单 1. 遇到查找错误停止的查找表(states-lookup-error.xslt)
<?xml version="1.0"?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:s="http://example.com/states.data"
version="1.0"
>
<xsl:output method="text"/>
<xsl:key name="state-lookup" match="s:state" use="s:abbr"/>
<xsl:variable name="states-top" select="document('')/*/s:states"/>
<xsl:template match="label">
<xsl:value-of select="name"/>
<xsl:text> of </xsl:text>
<xsl:apply-templates select="$states-top">
<xsl:with-param name="curr-label" select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="s:states">
<!-- This template updated to add a lookup error signal -->
<xsl:param name="curr-label"/>
<xsl:variable name="look-for" select="$curr-label/address/state"/>
<xsl:variable name="result"
select="key('state-lookup', $look-for)/s:name"/>
<xsl:if test="not($result)">
<xsl:message terminate="yes">
Lookup error on key: <xsl:value-of select="$look-for"/>
</xsl:message>
</xsl:if>
<!-- Push the string value of result to the output stream -->
<xsl:value-of select="$result"/>
</xsl:template>
<s:states>
<s:state><s:abbr>CO</s:abbr><s:name>Colorado</s:name></s:state>
<s:state><s:abbr>CT</s:abbr><s:name>Connecticut</s:name></s:state>
<s:state><s:abbr>ID</s:abbr><s:name>Idaho</s:name></s:state>
<s:state><s:abbr>NJ</s:abbr><s:name>New Jersey</s:name></s:state>
</s:states>
</xsl:transform>
上一篇技巧中介绍了这些代码的运作过程。惟一发生变化的是模板 match="s:states",增加了前面所说的错误通知技术。其原理是 XSLT key 永远不会返回空节点集,除非没有找到查找值。清单 2 是一个邮件标签文件,其中一项使用了查找表中没有的州缩写名。
清单 2. 邮件标签源文件
<?xml version="1.0"?>
<labels>
<label>
<name>Ezra Pound</name>
<address>
<street>45 Usura Place</street>
<city>Hailey</city>
<state>ZZ</state>
</address>
</label>
<label>
<name>William Williams</name>
<address>
<street>100 Wheelbarrow Blvd</street>
<city>Patterson</city>
<state>NJ</state>
</address>
</label>
</labels>
不同的 XSLT 处理程序以不同的方式报告 <xsl:message terminate="yes"> 消息,下面是 4XSLT 处理程序的输出结果。






