HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMajor

Efficiently generating HTML CSS table using Java

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
efficientlycssjavageneratingusinghtmltable

Problem

I am trying to generate an HTML table using Java. I have an object which I am iterating to make an HTML table.

StringBuilder sb = new StringBuilder();
sb.append("");
sb.append("");
sb.append("");
sb.append("");
sb.append(" ClientName");
sb.append("");
sb.append(" SyncCount");
sb.append("");
sb.append(" SyncPercentile");
sb.append("");
sb.append(" SyncAvg");
sb.append("");
sb.append(" SyncMax");
sb.append("");
sb.append(" AsyncCount");
sb.append("");
sb.append(" AsyncPercentile");
sb.append("");
sb.append(" AsyncAvg");
sb.append("");

for (DataMetrics metrics : dataMetricsList) {
    sb.append("");
    sb.append(" " + metrics.getName());
    sb.append("");
    sb.append(" " + metrics.getSyncCall());
    sb.append("");
    sb.append(" " + metrics.getSyncPercent());
    sb.append("");
    sb.append(" " + metrics.getSyncAvg());
    sb.append("");
    sb.append(" " + metrics.getSyncMax());
    sb.append("");
    sb.append(" " + metrics.getAsyncCall());
    sb.append("");
    sb.append(" " + metrics.getAsyncPercent());
    sb.append("");
    sb.append(" " + metrics.getAsyncAvg());
    sb.append("");
    sb.append("");
}
sb.append("");
sb.append("");
sb.append("");

System.out.println(sb.toString());


Somehow, the code looks pretty ugly to me in the way HTML and CSS are being used within StringBuilder. I am opting for code review to see whether we can improve anything here. Is there any better way of writing this code?

Solution

-
How about extracting the style=""s into the head?

sb.append("" +
"td { padding: 6px; border: 1px solid #ccc; text-align: left; }" + 
"th { background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;}" +
"");


-
You should write helper methods, that do the 'heavy lifting' for you:

void appendTag(StringBuilder sb, String tag, String contents) {
    sb.append('');
    sb.append(contents);
    sb.append("');
}
void appendDataCell(StringBuilder sb, String contents) {
    appendTag(sb, "td", contents);
}
void appendHeaderCell(StringBuilder sb, String contents) {
    appendTag(sb, "th", contents);
}


Please note, that if you are using StringBuilder you should not concatenate strings with +. You want to get rid of string concatenation, not do it.

If you want to get even more expressive you should take a look at existing template engines. They are optimized and mostly easy to use.

Suggesting mustache:

If you are using mustache, you can write a template like this:


  
    Table
    ...
  
  
    
     ....
    {{#metrics}}
      
        {{getName}}
        ...
      
    {{/metrics}}
  


and then render it via e.g.

public static void main(String[] args) throws IOException {
    HashMap scopes = new HashMap();
    scopes.put("metrics", dataMetricsList);

    Writer writer = new OutputStreamWriter(System.out);
    MustacheFactory mf = new DefaultMustacheFactory();
    Mustache mustache = mf.compile(new StringReader(getTemplateCodeFromAbove()), "example");
    mustache.execute(writer, scopes);
    writer.flush();
}


It depends on your use case, of course. If all you ever want is to render a single table, you are fine with StringBuilder. But if you find yourself repeating this, get an external library for it.

Code Snippets

sb.append("<style>" +
"td { padding: 6px; border: 1px solid #ccc; text-align: left; }" + 
"th { background: #333; color: white; font-weight: bold; padding: 6px; border: 1px solid #ccc; text-align: left;}" +
"</style>");
void appendTag(StringBuilder sb, String tag, String contents) {
    sb.append('<').append(tag).append('>');
    sb.append(contents);
    sb.append("</").append(tag).append('>');
}
void appendDataCell(StringBuilder sb, String contents) {
    appendTag(sb, "td", contents);
}
void appendHeaderCell(StringBuilder sb, String contents) {
    appendTag(sb, "th", contents);
}
<html>
  <head>
    <title>Table</title>
    <style>...</style>
  </head>
  <body>
    <table>
     <tr><th>....</th></tr>
    {{#metrics}}
      <tr>
        <td>{{getName}}</td>
        ...
      </tr>
    {{/metrics}}
  </body>
</html>
public static void main(String[] args) throws IOException {
    HashMap<String, Object> scopes = new HashMap<String, Object>();
    scopes.put("metrics", dataMetricsList);

    Writer writer = new OutputStreamWriter(System.out);
    MustacheFactory mf = new DefaultMustacheFactory();
    Mustache mustache = mf.compile(new StringReader(getTemplateCodeFromAbove()), "example");
    mustache.execute(writer, scopes);
    writer.flush();
}

Context

StackExchange Code Review Q#63331, answer score: 21

Revisions (0)

No revisions yet.