级别: 中级
Jack Herrington, 主编, Code Generation Network
2005 年 5 月 16 日
在 Java 代码中蕴涵着许多有价值的信息:所有类和接口,以及它们的实例变量和方法。您可以使用这些数据来创建文档,构建代码生成器,或者为项目报表提供度量标准。
Javadoc
是一个非常分解良好的应用程序。很多人认为它只是一个从一组 Java™ 文件中读取代码和注释来创建 HTML
的程序。但事实上,这款工具分为两个部分。第一部分是代码分析引擎,用来解析代码和注释。第二部分生成 HTML,但结果是,您可以使用称为 doclets 的扩展来改变这一部分。
对于本技巧,我使用 JELDoclet(参阅 参考资料) 从一组测试 Java 文件生成一个 XML 输出文件。然后,再使用 XSL 把这个 XML 文件格式化成一个简单的 HTML 文件。该 HTML 文件展示了 XML 文件所包含的数据。
下载 JELDoclet 后,使用下面的命令语法在一组文件上运行 JELDoclet:
javadoc -doclet JELDoclet -docletpath .. *.java
|
JELDoclet 的 test
目录包含一组测试 Java 文件。这个命令解析 test 目录中的所有 Java 文件,并且创建一个称为 out.xml 的文件。这个文件包含了 Javadoc 树中的所有信息。清单 1 展示了这个输出 XML 文件的一部分。
清单 1. JELDoclet 输出 XML 文件
<jel> <class superclass="Object" name="MyInterClass"> <extend name="MyInterface"> </extend> <comment> My interface implemented </comment> <fields> <field visibility="protected" fulltype="java.lang.String" type="String" name="_prot_string"> <comment> A protected string </comment> </field> <field visibility="public" fulltype="java.lang.String" type="String" name="_pub_string"> <comment> A public string </comment> </field> </fields> <methods> <constructor visibility="public" name="MyInterClass"> <comment> A no-argument constructor </comment> </constructor> <constructor visibility="public" name="MyInterClass"> <params> <param fulltype="java.lang.String" type="String" comment="A string." name="aString"> </param> ...
|
jel
标签包含了一系列 class
标签 —— 每个类对应一个。在 class
标签中是字段、方法和构造函数。XML 文件也包含相关的注释。
从 XML 创建 HTML
为这个 XML(清单 1中)生成 HTML 的第一步是从清单 2 中的基本标签模板开始。
清单 2. 基本 HTML 模板
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform version="2.0">
<xsl:output method="html" />
<xsl:template match="/"> <html><head><title>XDoclet output</title> <xsl:call-template name="css" />
</head> <body> <xsl:for-each select="/jel/class">
<h1> <xsl:choose> <xsl:when test="@abstract='true'">Interface: <xsl:value-of select="@name" /></xsl:when> <xsl:otherwise>Class : <xsl:value-of select="@name" /> ( <xsl:value-of select="@superclass" /> ) </xsl:otherwise> </xsl:choose> </h1>
<h2>Instance Variables</h2> <xsl:apply-templates select="fields/field" />
<h2>Constructors</h2> <xsl:apply-templates select="methods/constructor" />
<h2>Methods</h2> <xsl:apply-templates select="methods/method" />
<hr/> </xsl:for-each> </body> </html> </xsl:template>
|
在清单 2 的开始,我创建了 html
根标签和 head
部分。然后,我迭代了输入文件中的每个类。对于每个类,我在 h1
标签中输出类或接口的名称,并为 fields
、constructors
和 methods
应用模板。接着,我通过结束 body
和 html
标签而结束整个清单。
用于构建字段 HTML 的模板非常简单,如清单 3 所示。
清单 3. 字段模板
<xsl:template match="field"> <p class="field"> <xsl:value-of select="@visibility" /> <xsl:text> </xsl:text> <xsl:value-of select="@type" /> <xsl:text> </xsl:text> <xsl:value-of select="@name" /> </p> </xsl:template>
|
简洁的内容:我只输出了可见性、类型和名称。我使用了一个带有 class
字段的 paragraph
标签把它们括起来。后面在 CSS 中将用到 class
字段。
方法和构造函数模板与字段模板类似,如清单 4 所示。
清单 4. 方法和构造函数模板
<xsl:template match="method"> <p class="method"> <xsl:value-of select="@visibility" /> <xsl:text> </xsl:text> <xsl:value-of select="@type" /> <xsl:text> </xsl:text> <xsl:value-of select="@name" />( <xsl:apply-templates select="params" /> )</p> </xsl:template>
<xsl:template match="constructor"> <p class="method"> <xsl:value-of select="@visibility" /> <xsl:text> </xsl:text> <xsl:value-of select="@name" />( <xsl:apply-templates select="params" /> )</p> </xsl:template>
|
这里惟一的诀窍是,我需要将参数列表输出到每个构造函数或方法中。我使用 xsl:apply-templates
标签来处理,这个标签用来为 params
标签找到正确的模板 —— 在本例中,清单 5 展示了这个模板。
清单 5. 参数模板
<xsl:template match="params"> <xsl:for-each select="param"> <xsl:if test="position()>1">, </xsl:if> <xsl:value-of select="@type" /><xsl:text> </xsl:text> <xsl:value-of select="@name" /> </xsl:for-each> </xsl:template>
|
这里最吸引人的地方是,我想要在列表中的两个参数间插入逗号。因此我使用 xsl:if
命令,在第 2 个参数或后面的参数上插入逗号。
XSL 模板的最后一部分是 CSS,它使输出内容更加容易阅读(参阅清单 6)。
清单 6. CSS 模板
<xsl:template name="css"> <style> body { font-family: Arial, Verdana, sans serif;
font-size: small; } .method, .field { padding-left:50px; } </style> </xsl:template>
</xsl:stylesheet>
|
使用诸如 Arial 或 Verdana 这样的 sans-serif 字体,以使输出更加容易阅读。您可能使用的是 Courier 字体,但是我认为它会使页面看起来非常单调,并且让人觉得好像是用古老的打印机输出来的。最后,输出的结果看起来像图 1 那样。
图 1. 浏览器显示的最终 HTML
结束语
格
式化 HTML 仅仅是您可以对 Javadoc 工具的 XML 输出所做的事情之一。您可以像 XDoclet 所做的一样,使用 Javadoc
树中的信息(这里导出为 XML)来加强代码生成器的功能。您可以像 Eclipse 或 IntelliJ
一样,执行代码引用分析和重构。您也可以得到关于代码基的度量标准。获得 Java 代码完整的、结构化的 XML 表示,有助于提高您的生产力。
参考资料
关于作者