首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 xsl:message 调试样式表(1)

用 xsl:message 调试样式表(1)

回显打印是调试困难问题的最古老的方法之一。不管怎么说,这仍然是最简单、最快捷的方法。如果不能确定为何函数没有按预期工作,用 printf() 或类似的工具在控制台上打印几个变量就可以了解幕后发生了什么。
当然,必须有能够输出调试结果的控制台。XSLT 不一定具有 printf() 这样的东西。不过 XSLT 有一个与 printf() 对应的元素:xsl:message。xsl:message 元素不改变 XSLT 样式表生成的结果树,仅仅输出一些消息让程序员看到。一般输出到控制台,但也可能是对话框或者日志文件。无论输出到哪里,都是一种非常好的调试辅助手段。
xsl:message 元素是可选的。没有要求处理程序一定支持它。不过大部分处理程序都支持它,而且通常把消息输出到控制台。
是否激活了某个模板?如果输出不同于预期结果,首先要检查是否确实激活了模板。有很多原因可能造成模板被跳过,比如:
  • match属性中的元素名打错了
  • 错误的名称空间,尤其是当试图把默认名称空间中的元素与样式表中没有前缀的名称匹配时
  • 模式不匹配
这仅仅是部分可能的原因 。还可能有其他原因造成应该被激活的模板没有激活。为了检查是否执行了模板,可以在模板的开头加上 xsl:message 元素说明处理程序确实执行到了这里。比方说,假设要将 XHTML 文档转化成没有标记的普通文本。可以将类似  所示的消息添加到模板中:
清单 1. 用于调试的匹配 HTML 的模板规则
1
2
3
4
5
6
7
8
9
<xsl:template match="/">
  <xsl:message>Matched root node</xsl:message>
  <xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="html" xmlns:html="http://www.w3.org/1999/xhtml">
  <xsl:message>Matched html element</xsl:message>
  <book><xsl:apply-templates select="html"/></book>
</xsl:template>




运行该样式表的时候,如果看到 Matched root node 消息,就知道到了那里。如果没有看到 Matched html element 消息,就知道并没有执行到这里。这样就提供了确定问题所在的线索。很可能是 xsl:apply-templates 的 select 属性或者 htmltemplate 的 match 属性错了(这个例子是后一种情况,第二个模板应该与 html:html 匹配)。无论哪种情况,都会告诉您到哪里查找最可能出问题的地方。
包含 xsl:if 或 xsl:choose 语句的模板有多个分支。可以在每个分支中加上 xsl:message 元素来确定执行了哪一个(如果有的话)。比如, 显示了插入到 DocBook XSL 样式表中以确定为何转换无效的代码:
清单 2. 增加了调试指令的 DocBook XSL 模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<xsl:choose>
  <xsl:when test="caption">
    <xsl:message>CAPTION!</xsl:message>
    <fo:table-and-caption id="{$id}"
                          xsl:use-attribute-sets="table.properties">
      <xsl:apply-templates select="caption" mode="htmlTable"/>
      <fo:table xsl:use-attribute-sets="table.table.properties">
        <xsl:choose>
          <xsl:when test="$fop.extensions != 0 or
                          $passivetex.extensions != 0">
            <xsl:message>EXTENSIONS!</xsl:message>
            <xsl:attribute name="table-layout">fixed</xsl:attribute>
          </xsl:when>
        </xsl:choose>
        <xsl:attribute name="width">
          <xsl:choose>
            <xsl:when test="@width">
              <xsl:message>WIDTH ATTRIBUTE!</xsl:message>
              <xsl:value-of select="@width"/>
            </xsl:when>
            <xsltherwise>
              <xsl:message>NO WIDTH ATTRIBUTE!</xsl:message>100%
            </xsltherwise>
          </xsl:choose>
        </xsl:attribute>
        <xsl:call-template name="make-html-table-columns">
          <xsl:with-param name="count" select="$numcols"/>
        </xsl:call-template>
        <xsl:apply-templates select="thead" mode="htmlTable"/>
        <xsl:apply-templates select="tfoot" mode="htmlTable"/>
        <xsl:choose>
          <xsl:when test="tbody">
            <xsl:message>TBODY!</xsl:message>
            <xsl:apply-templates select="tbody" mode="htmlTable"/>
          </xsl:when>
          <xsltherwise>
            <xsl:message>NO TBODY!</xsl:message>
            <fo:table-body>
              <xsl:apply-templates select="tr" mode="htmlTable"/>
            </fo:table-body>
          </xsltherwise>
        </xsl:choose>
      </fo:table>
    </fo:table-and-caption>
    <xsl:copy-of select="$footnotes"/>
  </xsl:when>
  <xsltherwise>
     <xsl:message>NO CAPTION!</xsl:message>
    <fo:block id="{$id}"
              xsl:use-attribute-sets="informaltable.properties">
      <fo:table table-layout="auto"
                xsl:use-attribute-sets="table.table.properties">
        <xsl:attribute name="width">
          <xsl:choose>
            <xsl:when test="@width">
              <xsl:message>WIDTH ATTRIBUTE!</xsl:message>
              <xsl:value-of select="@width"/>
            </xsl:when>
            <xsltherwise>
              <xsl:message>NO WIDTH ATTRIBUTE!</xsl:message>
              100%
            </xsltherwise>
          </xsl:choose>
        </xsl:attribute>
        <xsl:call-template name="make-html-table-columns">
          <xsl:with-param name="count" select="$numcols"/>
        </xsl:call-template>
        <!--<xsl:apply-templates mode="htmlTable"/>-->
        <xsl:choose>
          <xsl:when test="tbody">
            <xsl:message>TBODY!</xsl:message>
            <xsl:apply-templates select="tbody" mode="htmlTable"/>
          </xsl:when>
          <xsltherwise>
            <xsl:message>NO TBODY!</xsl:message>
            <fo:table-body>
              <xsl:apply-templates select="tr" mode="htmlTable"/>
            </fo:table-body>
          </xsltherwise>
        </xsl:choose>
      </fo:table>
    </fo:block>
    <xsl:copy-of select="$footnotes"/>
  </xsltherwise>
</xsl:choose>




XSLT 模板可能比较复杂。要注意您的消息。我曾经多次犯过这样的错误,在错误的地方放上了 NO TBODY! 这样的消息声明。结果看到的消息完全是误导。调试困难的问题之前一定要安排好缩进和空白。通常,清理缩进本身就能发现问题所在。
返回列表