private String getSingleLineOfChildren(final List children) {
    final StringBuilder result = new StringBuilder();
    final Iterator childrenIt = children.iterator();
    boolean isFirst = true;

    while (childrenIt.hasNext()) {
      final Object child = childrenIt.next();

      if (!(child instanceof ContentNode)) {
        return null;
      } else {
        String content = child.toString();

        // if first item trims it from left
        if (isFirst) {
          content = Utils.ltrim(content);
        }

        // if last item trims it from right
        if (!childrenIt.hasNext()) {
          content = Utils.rtrim(content);
        }

        if (content.indexOf('\n') >= 0 || content.indexOf('\r') >= 0) {
          return null;
        }
        result.append(content);
      }

      isFirst = false;
    }

    return result.toString();
  }
  protected void serializePrettyHtml(
      final TagNode tagNode,
      final Writer writer,
      final int level,
      final boolean isPreserveWhitespaces,
      final boolean isLastNewLine)
      throws IOException {
    final List tagChildren = tagNode.getChildren();
    final String tagName = tagNode.getName();
    final boolean isHeadlessNode = Utils.isEmptyString(tagName);
    final String indent = isHeadlessNode ? "" : getIndent(level);

    if (!isPreserveWhitespaces) {
      if (!isLastNewLine) {
        writer.write("\n");
      }
      writer.write(indent);
    }
    serializeOpenTag(tagNode, writer, true);

    final boolean preserveWhitespaces = isPreserveWhitespaces || "pre".equalsIgnoreCase(tagName);

    boolean lastWasNewLine = false;

    if (!isMinimizedTagSyntax(tagNode)) {
      final String singleLine = getSingleLineOfChildren(tagChildren);
      final boolean dontEscape = dontEscape(tagNode);
      if (!preserveWhitespaces && singleLine != null) {
        writer.write(!dontEscape(tagNode) ? escapeText(singleLine) : singleLine);
      } else {
        final Iterator childIterator = tagChildren.iterator();
        while (childIterator.hasNext()) {
          final Object child = childIterator.next();
          if (child instanceof TagNode) {
            serializePrettyHtml(
                (TagNode) child,
                writer,
                isHeadlessNode ? level : level + 1,
                preserveWhitespaces,
                lastWasNewLine);
            lastWasNewLine = false;
          } else if (child instanceof ContentNode) {
            final String content = dontEscape ? child.toString() : escapeText(child.toString());
            if (content.length() > 0) {
              if (dontEscape || preserveWhitespaces) {
                writer.write(content);
              } else if (Character.isWhitespace(content.charAt(0))) {
                if (!lastWasNewLine) {
                  writer.write("\n");
                  lastWasNewLine = false;
                }
                if (content.trim().length() > 0) {
                  writer.write(
                      getIndentedText(Utils.rtrim(content), isHeadlessNode ? level : level + 1));
                } else {
                  lastWasNewLine = true;
                }
              } else {
                if (content.trim().length() > 0) {
                  writer.write(Utils.rtrim(content));
                }
                if (!childIterator.hasNext()) {
                  writer.write("\n");
                  lastWasNewLine = true;
                }
              }
            }
          } else if (child instanceof CommentNode) {
            if (!lastWasNewLine && !preserveWhitespaces) {
              writer.write("\n");
              lastWasNewLine = false;
            }
            final CommentNode commentNode = (CommentNode) child;
            final String content = commentNode.getCommentedContent();
            writer.write(
                dontEscape
                    ? content
                    : getIndentedText(content, isHeadlessNode ? level : level + 1));
          }
        }
      }

      if (singleLine == null && !preserveWhitespaces) {
        if (!lastWasNewLine) {
          writer.write("\n");
        }
        writer.write(indent);
      }

      serializeEndTag(tagNode, writer, false);
    }
  }