【问题标题】:What is a good technique for markup (HTML) generation?什么是标记(HTML)生成的好技术?
【发布时间】:2011-10-08 09:06:05
【问题描述】:

前段时间我在这里询问了good html object model in java。 我收到了指向Element Construction Set 项目的好答案:

我很高兴地使用这个 API 来快速构建一些 HTML 报告。

最近访问该项目网站时,我发现它已移至“The Apache Attic”,并且该项目的作者鼓励其用户切换到其他技术来生成标记。

我的问题是关于最后一句话:
还有什么其他好的标记生成技术?

我不是在构建 HTML 客户端,我只需要从服务器端数据生成一些 HTML 报告。我考虑过一些替代工具,但找不到下一个:

  • groovy 及其标记生成器
  • 免费标记
  • xslt
  • 碧玉报告

我喜欢 ECS 的地方是它纯粹是用 Java 编写的(不需要学习新的语法和概念,其他项目库可用),它非常小,它包含所有公共 html 元素和属性的定义(易于使用自动完成,无需 HTML 文档 -> 非常适合只有 HTML 基础知识的服务器端开发人员)

目前我正在浪费时间进行调查,与一些潜在的替代者一起玩,但我很高兴得到反馈,帮助我重新专注于完成我的任务。

对于这种用法,您会推荐哪些其他技术并具有与 ECS 相同的易用性?

【问题讨论】:

  • 那么您希望开发人员生成一些包含报告的 HTML 页面吗?您可能只使用纯 JSP 以及 Eclipse 中的 HTML 代码完成和语法高亮(我想说其他主要 IDE 也支持这一点)——这也告诉您是否缺少结束标记等。对我来说,似乎使用 ECS您仍然必须具备一些 HTML 和 CSS 知识,否则您将不知道要使用哪些元素/样式。
  • JSP 不是很轻量级的嵌入:我需要一个 jsp 编译器,并且觉得语法不会有好处... Velocity 或 FreeMarker 在这方面听起来更好。 ECS 需要基本的 HTML/CSS 知识,但自动补全有助于刷新我的记忆。
  • 是的,velocity 和 freemarker 绝对是更好的选择,但不幸的是,我不知道有任何编辑器支持 html 的完成/突出显示以及 velocity/freemarker。但是,说到 Eclipse,您可能能够使用它们并在 HTML/JSP 编辑器中打开文件——它确实提供了 HTML 代码完成等,但缺乏对速度/freemarker 的支持——然后首先创建 HTML 部分。然后你可以切换编辑器来填充velocity/freemarker的特定部分。
  • Intellij 至少对 freemarker 有很好的支持。我只是对它还不是很熟悉,我仍在寻找我想要采用的解决方案。我喜欢模板引擎用于非常简单的任务,但是一旦有很多逻辑,我觉得它们的可读性和可维护性都不是很好。

标签: java html api frameworks


【解决方案1】:

根据我的经验,最有效的是模板机制和转义标记的功能(处理 < & "' 就可以了)。选择任何支持循环和条件等基本控制结构的模板引擎。

不要用对象模型来生成 HTML。

【讨论】:

  • 我为什么要“不用对象模型来生成 HTML”。 ? GWT 和其他基于组件的客户端 API 成功地解决了它:-)
  • GWT、JSF 等在浏览器和服务器之间同步状态,因此它们需要在 DOM 和组件模型之间进行某种映射。您只在一个方向生成报告(如果我理解正确的话)。我认为仅仅为此而建造一棵树是一种额外的努力,而且不值得。模板更容易。
  • 非常正确。我不喜欢使用模板(和 JSP)的一点是,当其中有太多逻辑时,它会变得一团糟。然后我可以引入一个“演示模型”来避免复杂的模板,但这也是额外的努力。我不喜欢的另一件事是对象模型更改时出现的维护问题。
【解决方案2】:

这里有 4 个解决方案。

第一个可能是最好的:https://j2html.com/

// https://j2html.com/examples.html
@Test
public void test() {
    String s = document(
        html(
            head(
                title("Title"),
                link().withRel("stylesheet").withHref("/css/main.css")),
            body(
                main(attrs("#main.content"),
                    h1("Heading!"))))).toString();
    assertEquals("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"
        + "<html>\n"
        + "  <head>\n"
        + "    <title>\n"
        + "      Title\n"
        + "    </title>\n"
        + "    <link type=\"text/css\" rel=\"stylesheet\" href=\"/css/main.css\">\n"
        + "  </head>\n"
        + "  <body>\n"
        + "    <main id=\"main\" class=\"content\">\n"
        + "      <h1>\n"
        + "        Heading!\n"
        + "      </h1>\n"
        + "    </main>\n"
        + "  </body>\n"
        + "</html>\n", JtidyTest.tidyHtml(s));
}

它不支持漂亮打印。为此使用 jtidy:

public static String tidyHtml(String inputHtml) {
    Properties oProps = new Properties();
    oProps.setProperty("new-blocklevel-tags", "main");

    Tidy tidy = new Tidy();
    tidy.setConfigurationFromProps(oProps);
    tidy.setXHTML(false);
    tidy.setDocType("loose");
    tidy.setQuiet(true);
    tidy.setShowWarnings(false);
    tidy.setTidyMark(false);
    tidy.setIndentContent(true);
    StringWriter writer = new StringWriter();
    tidy.parse(new StringReader(inputHtml), writer);
    return writer.toString().replace("\r", "");
}

以下两个示例/解决方案仅使用 Java 自己的 XML 内容,因此不提供显式 HTML 支持,这有点不方便。

来自对象模型:

@Test
public void test() throws Exception {
    Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

    Element htmlElement = doc.createElement("html");
    htmlElement.setAttribute("xmlns", "http://www.w3.org/1999/xhtml");
    doc.appendChild(htmlElement);

    Element headElement = doc.createElement("head");
    htmlElement.appendChild(headElement);

    Element titleElement = doc.createElement("title");
    titleElement.appendChild(doc.createTextNode("The title of the page &"));
    headElement.appendChild(titleElement);

    assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\"?><html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
            + "<head>\n"
            + "<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n"
            + "<title>The title of the page &amp;</title>\n"
            + "</head>\n"
            + "</html>\n",
            transform(doc));
}

static String transform(Document doc) {
    try {
        DOMSource domSource = new DOMSource(doc);
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.transform(domSource, result);
        return writer.toString().replace("\r", "");
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

完整代码:https://github.com/jjYBdx4IL/java-evaluation/blob/master/src/test/java/tests/javax/xml/XhtmlGenTest.java

直接流式传输:

@Test
public void testGenerateXHTML() throws Exception {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
    XMLStreamWriter xml = outputFactory.createXMLStreamWriter(baos);

    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();

    assertEquals("<?xml version='1.0' encoding='UTF-8'?><html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>The title of the page</title></head></html>",
            baos.toString("UTF-8"));
}

完整代码:https://github.com/jjYBdx4IL/java-evaluation/blob/master/src/test/java/tests/javax/xml/stream/XMLStreamWriterTest.java

您也可以考虑 ECS,但它已停用,并且不支持对特殊字符(如 &)的隐式处理。我已将其更新为使用 Java 8 进行编译:https://github.com/jjYBdx4IL/misc/tree/master/ecs 不确定何时将其部署到 maven central tho。我还对其进行了修改以包含 javadoc、源代码和调试符号,所有这些都是 maven Central 上的现有发行版所不提供的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多