2009-06-05 82 views
10

有誰知道如何以編程方式生成一個HTMLDocument對象,而不需要在外部生成一個字符串,然後使用HTMLEditorKit#read來分析它?我問的兩個原因:使用Java編程生成HTMLDocument

首先,我的HTML生成例程需要非常快,我認爲將字符串解析爲內部模型比直接構建此模型成本更高。其次,面向對象的方法可能會導致更乾淨的代碼。

我還應該提到,出於許可原因,我不能訴諸使用除JVM附帶的庫之外的任何庫。

感謝, 湯姆

+0

我們在說HTML或XML嗎? – 2009-06-05 14:23:13

+0

爲什麼你需要解析你生成的HTML?你是否需要能夠插入可能失效的內聯HTML? – 2009-06-05 14:24:01

+0

感謝您的問題: mmyers:HTML 奧利弗: 對不起,我沒有說清楚。如果我正確理解你的問題,我將從HTML中生成一個HTMLDocument(使用HTMLEditorKit#read),由JTextPane渲染。 – 2009-06-05 14:33:21

回答

9

一個面向對象的方法是使用一種稱爲ECS庫。

這是相當簡單的圖書館,並沒有改變年齡。然後,HTML 4.01規範也沒有改變;)我使用了ECS,並認爲它比僅使用Strings或StringBuffers/StringBuilders生成大型HTML片段要好得多。

小例子:

Option optionElement = new Option(); 
optionElement.setTagText("bar"); 
optionElement.setValue("foo"); 
optionElement.setSelected(false); 

optionElement.toString()將現在的產量:

<option value='foo'>bar</option> 

庫支持HTML 4.0和XHTML。最初困擾我的唯一一件事很多是與XHTML版本相關的類名稱以小寫字母開頭:option,input,a,tr等,這違背了最基本的Java約定。但是如果你想使用XHTML,那麼你可以習慣這種方式;至少我做了,驚人的快。

1

您可能想用render()方法構建一些Element對象,然後將它們組裝到樹結構中;用訪問算法,你可以繼續設置值,然後渲染整個事物。

PS:你有沒有考慮過一些像freemarker這樣的模板引擎?

0

您可以使用像JDom或Xom或XStream的任何體面的xml庫。 Html只是XML的一個特例。或者,您可以使用現有的模板引擎之一作爲服務器端java,如jsp或velocity。

3

我認爲通過類似於StringBuilder(或直接向流)手動生成HTML將成爲您的最佳選擇,特別是如果您不能使用任何外部庫。

無法使用任何外部庫,您將在開發速度而不是性能方面受到更多影響。

7

我會研究JSP如何工作 - 即,它們編譯成一個基本上是一大串StringBuffer附加的servlet。這些標籤也可以編譯成Java代碼片段。這很麻煩,但非常快,除非你深入瞭解Tomcat的工作目錄,否則你永遠不會看到這些代碼。也許你想要的是從一個類似JSP的HTML中心視圖實際編寫HTML代碼,併爲循環添加標籤等,並在你的項目內部使用類似的代碼生成引擎和編譯器。

或者,您只需在一個實用程序類中處理StringBuilder,該類具有「openTag」,「closeTag」,「openTagWithAttributes」,「startTable」等方法......它可以使用Builder模式,你的代碼看起來像:

public static void main(String[] args) { 
    TableBuilder t = new TableBuilder(); 
    t.start().border(3).cellpadding(4).cellspacing(0).width("70%") 
     .startHead().style("font-weight: bold;") 
     .newRow().style("border: 2px 0px solid grey;") 
      .newHeaderCell().content("Header 1") 
      .newHeaderCell().colspan(2).content("Header 2") 
     .end() 
     .startBody() 
     .newRow() 
      .newCell().content("One/One") 
      .newCell().rowspan(2).content("One/Two") 
      .newCell().content("One/Three") 
     .newRow() 
      .newCell().content("Two/One") 
      .newCell().content("Two/Three") 
     .end() 
    .end(); 
    System.out.println(t.toHTML()); 
} 
2

javax.swing.text.html中有HTMLWriter和他人之間HTMLDocument類。我沒有用過它們。我已經使用了HtmlWriter中的.Net,它完全符合你的要求,但是java版本可能不會相同。

這裏是DOC:http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/html/HTMLWriter.html

另外,我無法想象一個StringBuilder比與對象層構建慢。在我看來,任何面向對象的方法都必須構建對象圖形,然後生成字符串。不使用原始字符串的主要原因是你一定會得到編碼錯誤以及其他錯誤產生格式錯誤的文檔。

選項2:您可以使用您最喜歡的XML API並生成XHTML。

4

當處理XHTML時,我已經使用Java 6的XMLStreamWriter接口取得了很大的成功。

OutputStream destination = ...; 
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); 
XMLStreamWriter xml = outputFactory.createXMLStreamWriter(destination); 

xml.writeStartDocument(); 
xml.writeStartElement("html"); 
xml.writeDefaultNamespace("http://www.w3.org/1999/xhtml"); 

xml.writeStartElement("head"); 
xml.writeStartElement("title"); 
xml.writeCharacters("The title of the page"); 
xml.writeEndElement(); 
xml.writeEndElement(); 

xml.writeEndElement(); 
xml.writeEndDocument(); 
1

看樣子,你可以完成你所使用HTMLDocument.BlockElementHTMLDocument.BlockElement對象的直接施工嘗試。這些構造函數的簽名至少表明直接使用是可能的。

我會建議檢查OpenJDK中的Swing源代碼,看看解析器如何處理這個問題,並從那裏派生出你的邏輯。

我也建議這種優化可能爲時過早,也許這應該是速度優化的替代品,如果這確實成爲應用程序中的性能熱點,那麼只能引入更簡單的方法(即生成HTML文本)。

0

基本上可以使用插入方法insertBeforeEnd(),insertAfterEnd(),insertBeforeStart(),insertAfterStart()將html插入到HTMLDocument中。 您提供了您想要插入的html的方法以及您希望插入html的文檔樹中的位置。

例如。

doc.insertBeforeEnd(element,html);

HTMLDocument類還提供遍歷文檔樹的方法。