11

有谁知道如何在 Java 中以编程方式生成 HTMLDocument 对象,而无需在外部生成字符串,然后使用 HTMLEditorKit#read 解析它?我问的两个原因:

首先,我的 HTML 生成例程需要非常快,并且我假设将字符串解析为内部模型比直接构建此模型成本更高。

其次,面向对象的方法可能会产生更简洁的代码。

我还应该提到,出于许可的原因,除了 JVM 附带的库之外,我不能使用任何库。

谢谢,汤姆

4

9 回答 9

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 版本相关的类的名称以小写字母开头:optioninputatr等等,这与最基本的 Java 约定背道而驰。但是,如果您想使用 XHTML,您可以习惯这一点。至少我做到了,出奇的快。

于 2009-06-05T14:29:25.673 回答
7

我会研究 JSP 是如何工作的 - 即,它们编译成一个 servlet,它基本上是一组巨大的 StringBuffer 附加组件。这些标签还编译成 Java 代码片段。这很混乱,但非常非常快,除非您深入研究 Tomcat 的工作目录,否则您永远不会看到此代码。也许您想要的是从一个以 HTML 为中心的视图(如 JSP)实际编写 HTML 生成代码,并为循环添加标签等,并在项目内部使用类似的代码生成引擎和编译器。

或者,只需在具有“openTag”、“closeTag”、“openTagWithAttributes”、“startTable”等方法的实用程序类中自己处理 StringBuilder……它可以使用 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());
}
于 2009-06-05T14:33:53.650 回答
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();
于 2009-06-05T14:39:18.197 回答
3

我认为通过 StringBuilder(或直接生成流)之类的东西手动生成 HTML 将是您的最佳选择,尤其是在您不能使用任何外部库的情况下。

无法使用任何外部库,您将在开发速度而非性能方面遭受更多损失。

于 2009-06-05T14:31:05.577 回答
2

javax.swing.text.html 有HTMLWriterHTMLDocument类等等。我没有使用过它们。我使用了HtmlWriterin .Net,它完全符合您的要求,但 java 版本可能不一样。

这是文档:http: //java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/html/HTMLWriter.html

另外,我无法想象StringBuilder比使用对象层构建要慢。在我看来,任何面向对象的方法都必须构建对象图然后生成字符串。不使用原始字符串的主要原因是您肯定会遇到编码错误以及其他导致格式错误的文档的错误。

选项 2:您可以使用自己喜欢的 XML api 并生成 XHTML。

于 2009-06-05T14:34:37.567 回答
1

您可能希望使用 render() 方法构建一些 Element 对象,然后将它们组装成树结构;通过访问算法,您可以继续设置值,然后渲染整个事物。

PS:你有没有考虑过像freemarker这样的模板引擎?

于 2009-06-05T14:30:09.477 回答
1

看来您可以使用直接构造HTMLDocument.BlockElementHTMLDocument.BlockElement对象来完成您正在尝试的事情。这些构造函数有一个签名,表明至少可以直接使用。

我建议检查 OpenJDK 中的 Swing 源代码,以了解解析器如何处理此问题,并从中得出您的逻辑。

我还建议这种优化可能还为时过早,也许这应该是一个更简单的方法(即生成 HTML 文本)的速度优化替代,只有在这确实成为应用程序中的性能热点时才引入。

于 2009-06-05T15:36:05.620 回答
0

您可以使用任何像样的 xml 库,例如 JDom 或 Xom 或 XStream。Html 只是 XML 的一个特例。

或者,您可以使用现有的服务器端 java 模板引擎之一,如 jsp 或速度。

于 2009-06-05T14:30:57.387 回答
0

基本上,您可以使用插入方法之一将 html 插入 HTMLDocument,insertBeforeEnd()、insertAfterEnd()、insertBeforeStart()、insertAfterStart()。您为方法提供要插入的 html 以及要插入 html 在文档树中的位置。

例如。

doc.insertBeforeEnd(元素, html);

HTMLDocument 类还提供了遍历文档树的方法。

于 2009-06-06T01:30:13.223 回答