使用 Java 编程生成 HTMLDocument

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/956112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:33:28  来源:igfitidea点击:

Programmatic HTMLDocument generation using Java

javahtmlconstruction

提问by Tom Klapiscak

Does anyone know how to generate an HTMLDocument object programmatically in Java without resorting to generating a String externally and then using HTMLEditorKit#read to parse it? Two reasons I ask:

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

Firstly my HTML generation routine needs to be very fast and I assume that parsing a string into an internal model is more costly than directly constructing this model.

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

Secondly, an object-oriented approach would likely result in cleaner code.

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

I should also mention that, for licensing reasons, I can't resort to using any libraries other than those shipped with the JVM.

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

Thanks, Tom

谢谢,汤姆

回答by Jonik

One object-oriented approach is to use a library called ECS.

一种面向对象的方法是使用名为ECS的库。

It is quite simple library, and has not changed for ages. Then again, the HTML 4.01 spec has not changed either ;) I've used ECS and consider it far better than generating large HTML fragments with just Strings or StringBuffers/StringBuilders.

这是一个非常简单的图书馆,而且已经很久没有改变了。再说一次,HTML 4.01 规范也没有改变;) 我使用过 ECS 并认为它比仅使用 Strings 或 StringBuffers/StringBuilders 生成大型 HTML 片段要好得多。

Small example:

小例子:

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

optionElement.toString()would now yield:

optionElement.toString()现在会产生:

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

The library supports both HTML 4.0 and XHTML. The only thing that initially bothered me a lotwas that names of classes related to the XHTML version started with a lowercase letter: option, input, a, tr, and so on, which goes against the most basic Java conventions. But that's something you can get used to if you want to use XHTML; at least I did, surprisingly fast.

该库支持 HTML 4.0 和 XHTML。最初困扰我的唯一的事情很多是涉及到开始以小写字母的XHTML版本的类名称:optioninputatr,等等,这违背了最基本的Java约定。但是,如果您想使用 XHTML,您可以习惯这种方式;至少我做到了,出奇的快。

回答by JeeBee

I'd look into how JSPs work - i.e., they compile down into a servlet that is basically one huge long set of StringBuffer appends. The tags also compile down into Java code snippets. This is messy, but very very fast, and you never see this code unless you delve into Tomcat's work directory. Maybe what you want is to actually code your HTML generation from a HTML centric view like a JSP, with added tags for loops, etc, and use a similar code generation engine and compiler internally within your project.

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

Alternatively, just deal with the StringBuilder yourself in a utility class that has methods for "openTag", "closeTag", "openTagWithAttributes", "startTable", and so on... it could use a Builder pattern, and your code would look like:

或者,只需在具有“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());
}

回答by Adam Paynter

When dealing with XHTML, I have had much success using Java 6's XMLStreamWriterinterface.

在处理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();

回答by AgileJon

I think manually generating your HTML via something like a StringBuilder (or directly to a stream) is going to be your best option, especially if you cannot use any external libraries.

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

Not being able to use any external libraries, you will suffer more in terms of speed of development rather than performance.

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

回答by Ryan Cook

javax.swing.text.html has HTMLWriterand HTMLDocumentclass among others. I have not used them. I have used the HtmlWriterin .Netand it does exactly what you want, but the java version may not work out to be the same.

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

Here is the doc: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/text/html/HTMLWriter.html

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

Also, I can't imagine a StringBuilderbeing slower than building with an object layer. It seems to me that any object oriented approach would have to build the object graph AND then produce the string. The main reason not to use raw strings for this stuff is that you are sure to get encoding errors as well as other mistakes that produce malformed documents.

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

Option 2: You could use your favorite XML api's and produce XHTML.

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

回答by Tetsujin no Oni

It appears that you can accomplish what you are attempting using direct construction of HTMLDocument.BlockElementand HTMLDocument.BlockElementobjects. Theses constructors have a signature that suggests direct use is possible, at least.

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

I would suggest examining the Swing sources in OpenJDK to see how the parser handles this, and derive your logic from there.

我建议检查 OpenJDK 中的 Swing 源代码,看看解析器如何处理这个问题,并从中派生出你的逻辑。

I would also suggest that this optimization may be premature, and perhaps this should be a speed-optimized replacement for a simpler approach (i.e. generating the HTML text) only introduced if this really does become a performance hotspot in the application.

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

回答by Manrico Corazzi

You may want to build some Element object with a render() method, and then assemble them in a tree structure; with a visit algorhytm you may then proceed to set the values and then render the whole thing.

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

PS: have you considered some templating engine like freemarker?

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

回答by Marko

You can use any decent xml library like JDom or Xom or XStream. Html is just a special case of XML.

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

Or, you can use one of the existing templating engines for server side java like jsp or velocity.

或者,您可以将现有的模板引擎之一用于服务器端 java,例如 jsp 或velocity。

回答by objects

Basically you can insert html into your HTMLDocument using one of the insert methods, insertBeforeEnd(), insertAfterEnd(), insertBeforeStart(), insertAfterStart(). You supply the method with the html you want to insert and the position in the document tree that you want the html inserted.

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

eg.

例如。

doc.insertBeforeEnd(element, html);

doc.insertBeforeEnd(元素, html);

The HTMLDocument class also provided methods for traversing the document tree.

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