級別: 中級
Jack Herrington, 主編, Code Generation Network
2005 年 5 月 16 日
在 Java 代碼中蘊涵著許多有價值的信息:所有類和接口,以及它們的實例變量和方法。您可以使用這些數(shù)據(jù)來創(chuàng)建文檔,構(gòu)建代碼生成器,或者為項目報表提供度量標準。
Javadoc
是一個非常分解良好的應用程序。很多人認為它只是一個從一組 Java? 文件中讀取代碼和注釋來創(chuàng)建 HTML
的程序。但事實上,這款工具分為兩個部分。第一部分是代碼分析引擎,用來解析代碼和注釋。第二部分生成 HTML,但結(jié)果是,您可以使用稱為 doclets 的擴展來改變這一部分。
對于本技巧,我使用 JELDoclet(參閱 參考資料) 從一組測試 Java 文件生成一個 XML 輸出文件。然后,再使用 XSL 把這個 XML 文件格式化成一個簡單的 HTML 文件。該 HTML 文件展示了 XML 文件所包含的數(shù)據(jù)。
下載 JELDoclet 后,使用下面的命令語法在一組文件上運行 JELDoclet:
javadoc -doclet JELDoclet -docletpath .. *.java
|
JELDoclet 的 test
目錄包含一組測試 Java 文件。這個命令解析 test 目錄中的所有 Java 文件,并且創(chuàng)建一個稱為 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
標簽中是字段、方法和構(gòu)造函數(shù)。XML 文件也包含相關的注釋。
從 XML 創(chuàng)建 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 的開始,我創(chuàng)建了 html
根標簽和 head
部分。然后,我迭代了輸入文件中的每個類。對于每個類,我在 h1
標簽中輸出類或接口的名稱,并為 fields
、constructors
和 methods
應用模板。接著,我通過結(jié)束 body
和 html
標簽而結(jié)束整個清單。
用于構(gòu)建字段 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>
|
簡潔的內(nèi)容:我只輸出了可見性、類型和名稱。我使用了一個帶有 class
字段的 paragraph
標簽把它們括起來。后面在 CSS 中將用到 class
字段。
方法和構(gòu)造函數(shù)模板與字段模板類似,如清單 4 所示。
清單 4. 方法和構(gòu)造函數(shù)模板
<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>
|
這里惟一的訣竅是,我需要將參數(shù)列表輸出到每個構(gòu)造函數(shù)或方法中。我使用 xsl:apply-templates
標簽來處理,這個標簽用來為 params
標簽找到正確的模板 —— 在本例中,清單 5 展示了這個模板。
清單 5. 參數(shù)模板
<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>
|
這里最吸引人的地方是,我想要在列表中的兩個參數(shù)間插入逗號。因此我使用 xsl:if
命令,在第 2 個參數(shù)或后面的參數(shù)上插入逗號。
XSL 模板的最后一部分是 CSS,它使輸出內(nèi)容更加容易閱讀(參閱清單 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 字體,但是我認為它會使頁面看起來非常單調(diào),并且讓人覺得好像是用古老的打印機輸出來的。最后,輸出的結(jié)果看起來像圖 1 那樣。
圖 1. 瀏覽器顯示的最終 HTML
結(jié)束語
格
式化 HTML 僅僅是您可以對 Javadoc 工具的 XML 輸出所做的事情之一。您可以像 XDoclet 所做的一樣,使用 Javadoc
樹中的信息(這里導出為 XML)來加強代碼生成器的功能。您可以像 Eclipse 或 IntelliJ
一樣,執(zhí)行代碼引用分析和重構(gòu)。您也可以得到關于代碼基的度量標準。獲得 Java 代碼完整的、結(jié)構(gòu)化的 XML 表示,有助于提高您的生產(chǎn)力。
參考資料
關于作者