Utility class to print out DOM : DOM Document « XML « Java






Utility class to print out DOM

   
/*******************************************************************************
 * Copyright (c) 2008 IBM Corporation and Others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Kentarou FUKUDA - initial API and implementation
 *******************************************************************************/


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.html.HTMLTitleElement;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;

/**
 * Utility class to print out DOM
 */
@SuppressWarnings("nls")
public class DomPrintUtil {

  /**
   * Default encoding of this utility. (UTF8)
   */
  public static final String UTF8 = "UTF8";

  private static final String LINE_SEP = System.getProperty("line.separator");
  private static final String EMPTY_STR = "";

  private static final String LT = "<";
  private static final String GT = ">";
  private static final String AMP = "&";
  private static final String QUAT = "\"";
  private static final String SINGLE_QUAT = "'";

  private static final String ESC_LT = "&lt;";
  private static final String ESC_GT = "&gt;";
  private static final String ESC_AMP = "&amp;";

  private Document document;
  private int whatToShow = NodeFilter.SHOW_ALL;
  private NodeFilter nodeFilter = null;
  private boolean entityReferenceExpansion = false;

  private boolean indent = true;
  private boolean escapeTagBracket = false;

  private AttributeFilter attrFilter = null;

  /**
   * AttributeFilter defines the behavior of a filter that is used for
   * converting attributes of each Element into String.
   */
  public interface AttributeFilter {

    /**
     * Check whether a specified attribute is converted into String.
     * 
     * @param element
     *            the target Element
     * @param attr
     *            the target attribute
     * @return true to print the attribute, false to ignore the attribute
     */
    public boolean acceptNode(Element element, Node attr);
  }

  /**
   * Constructor of DOM print utility.
   * 
   * @param document
   *            the target document
   */
  public DomPrintUtil(Document document) {
    this.document = document;
  }

  private String getXMLString(String targetS) {
    return targetS.replaceAll(AMP, ESC_AMP).replaceAll(LT, ESC_LT)
        .replaceAll(GT, ESC_GT);
  }

  private String getAttributeString(Element element, Node attr) {
    if (null == attrFilter || attrFilter.acceptNode(element, attr)) {
      String value = getXMLString(attr.getNodeValue());
      String quat = QUAT;
      if (value.indexOf(QUAT) > 0) {
        quat = SINGLE_QUAT;
      }
      return " " + attr.getNodeName() + "=" + quat + value + quat;
    }
    return EMPTY_STR;
  }

  private boolean checkNewLine(Node target) {
    if (indent && target.hasChildNodes()) {
      short type = target.getFirstChild().getNodeType();
      if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) {
        return false;
      }
      return true;
    }
    return false;
  }

  /**
   * Returns XML text converted from the target DOM
   * 
   * @return String format XML converted from the target DOM
   */
  public String toXMLString() {
    StringBuffer tmpSB = new StringBuffer(8192);

    TreeWalkerImpl treeWalker = new TreeWalkerImpl(document, whatToShow,
        nodeFilter, entityReferenceExpansion);

    String lt = escapeTagBracket ? ESC_LT : LT;
    String gt = escapeTagBracket ? ESC_GT : GT;
    String line_sep = indent ? LINE_SEP : EMPTY_STR;

    Node tmpN = treeWalker.nextNode();
    boolean prevIsText = false;

    String indentS = EMPTY_STR;
    while (tmpN != null) {
      short type = tmpN.getNodeType();
      switch (type) {
      case Node.ELEMENT_NODE:
        if (prevIsText) {
          tmpSB.append(line_sep);
        }
        tmpSB.append(indentS + lt + tmpN.getNodeName());
        NamedNodeMap attrs = tmpN.getAttributes();
        int len = attrs.getLength();
        for (int i = 0; i < len; i++) {
          Node attr = attrs.item(i);
          String value = attr.getNodeValue();
          if (null != value) {
            tmpSB.append(getAttributeString((Element) tmpN, attr));
          }
        }
        if (tmpN instanceof HTMLTitleElement && !tmpN.hasChildNodes()) {
          tmpSB.append(gt + ((HTMLTitleElement) tmpN).getText());
          prevIsText = true;
        } else if (checkNewLine(tmpN)) {
          tmpSB.append(gt + line_sep);
          prevIsText = false;
        } else {
          tmpSB.append(gt);
          prevIsText = true;
        }
        break;
      case Node.TEXT_NODE:
        if (!prevIsText) {
          tmpSB.append(indentS);
        }
        tmpSB.append(getXMLString(tmpN.getNodeValue()));
        prevIsText = true;
        break;
      case Node.COMMENT_NODE:
        String comment;
        if (escapeTagBracket) {
          comment = getXMLString(tmpN.getNodeValue());
        } else {
          comment = tmpN.getNodeValue();
        }
        tmpSB.append(line_sep + indentS + lt + "!--" + comment + "--"
            + gt + line_sep);
        prevIsText = false;
        break;
      case Node.CDATA_SECTION_NODE:
        tmpSB.append(line_sep + indentS + lt + "!CDATA["
            + tmpN.getNodeValue() + "]]" + line_sep);
        break;
      case Node.DOCUMENT_TYPE_NODE:
        if (tmpN instanceof DocumentType) {
          DocumentType docType = (DocumentType) tmpN;
          String pubId = docType.getPublicId();
          String sysId = docType.getSystemId();
          if (null != pubId && pubId.length() > 0) {
            if (null != sysId && sysId.length() > 0) {
              tmpSB.append(lt + "!DOCTYPE " + docType.getName()
                  + " PUBLIC \"" + pubId + " \"" + sysId
                  + "\">" + line_sep);
            } else {
              tmpSB.append(lt + "!DOCTYPE " + docType.getName()
                  + " PUBLIC \"" + pubId + "\">" + line_sep);
            }
          } else {
            tmpSB.append(lt + "!DOCTYPE " + docType.getName()
                + " SYSTEM \"" + docType.getSystemId() + "\">"
                + line_sep);

          }
        } else {
          System.out
              .println("Document Type node does not implement DocumentType: "
                  + tmpN);
        }
        break;
      default:
        System.out.println(tmpN.getNodeType() + " : "
            + tmpN.getNodeName());
      }

      Node next = treeWalker.firstChild();
      if (null != next) {
        if (indent && type == Node.ELEMENT_NODE) {
          indentS = indentS + " ";
        }
        tmpN = next;
        continue;
      }

      if (tmpN.getNodeType() == Node.ELEMENT_NODE) {
        tmpSB.append(lt + "/" + tmpN.getNodeName() + gt + line_sep);
        prevIsText = false;
      }

      next = treeWalker.nextSibling();
      if (null != next) {
        tmpN = next;
        continue;
      }

      tmpN = null;
      next = treeWalker.parentNode();
      while (null != next) {
        if (next.getNodeType() == Node.ELEMENT_NODE) {
          if (indent) {
            if (indentS.length() > 0) {
              indentS = indentS.substring(1);
            } else {
              System.err.println("indent: " + next.getNodeName()
                  + " " + next);
            }
          }
          tmpSB.append(line_sep + indentS + lt + "/"
              + next.getNodeName() + gt + line_sep);
          prevIsText = false;
        }
        next = treeWalker.nextSibling();
        if (null != next) {
          tmpN = next;
          break;
        }
        next = treeWalker.parentNode();
      }
    }
    return tmpSB.toString();
  }

  /*
   * (non-Javadoc)
   * 
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return toXMLString();
  }

  /**
   * Set whatToShow attribute to TreeWalker used in the utility.
   * 
   * @param whatToShow
   *            the attribute determines which types of node are presented via
   *            the TreeWalker. The values are defined in the NodeFilter
   *            interface.
   * @see TreeWalkerImpl
   */
  public void setWhatToShow(int whatToShow) {
    this.whatToShow = whatToShow;
  }

  /**
   * Set NodeFilter to TreeWalker used in the utility.
   * 
   * @param nodeFilter
   *            the filter used to screen nodes
   * @see TreeWalkerImpl
   */
  public void setNodeFilter(NodeFilter nodeFilter) {
    this.nodeFilter = nodeFilter;
  }

  /**
   * Set the entity reference expansion flag to TreeWalker used in the
   * utility.
   * 
   * @param entityReferenceExpansion
   *            the flag to determine whether the children of entity reference
   *            nodes are visible to TreeWalker.
   * @see TreeWalkerImpl
   */
  public void setEntityReferenceExpansion(boolean entityReferenceExpansion) {
    this.entityReferenceExpansion = entityReferenceExpansion;
  }

  /**
   * Set the number of space characters used for indent
   * 
   * @param indent
   *            the number of space characters used for indent
   */
  public void setIndent(boolean indent) {
    this.indent = indent;
  }

  /**
   * Determine to escape Tag bracket ('<','>') or not. Please set true if you
   * want to print out DOM into &lt;pre&gt; section of HTML.
   * 
   * @param escapeTagBracket
   *            if true, print Tag bracket as escaped format ({@literal '&lt;',
   *            '&gt;'})
   * 
   */
  public void setEscapeTagBracket(boolean escapeTagBracket) {
    this.escapeTagBracket = escapeTagBracket;
  }

  /**
   * Set AttributeFilter to define the behavior for printing attributes of
   * each Element.
   * 
   * @param attrFilter
   *            the AttributeFilter to set
   */
  public void setAttrFilter(AttributeFilter attrFilter) {
    this.attrFilter = attrFilter;
  }

  /**
   * Print out the target Document.
   * 
   * @param filePath
   *            the target file path
   * @throws IOException
   */
  public void writeToFile(String filePath) throws IOException {
    writeToFile(new File(filePath), UTF8);
  }

  /**
   * Print out the target Document.
   * 
   * @param file
   *            the target File
   * @throws IOException
   */
  public void writeToFile(File file) throws IOException {
    writeToFile(file, UTF8);
  }

  /**
   * Print out the target Document in specified encoding
   * 
   * @param filePath
   *            the target file path
   * @param encode
   *            the target encoding
   * @throws IOException
   */
  public void writeToFile(String filePath, String encode) throws IOException {
    writeToFile(new File(filePath), encode);
  }

  /**
   * Print out the target Document in specified encoding
   * 
   * @param file
   *            the target file
   * @param encode
   *            the target encoding
   * @throws IOException
   */
  public void writeToFile(File file, String encode) throws IOException {
    PrintWriter tmpPW = new PrintWriter(new OutputStreamWriter(
        new FileOutputStream(file), encode));
    tmpPW.println(toXMLString());
    tmpPW.flush();
    tmpPW.close();
  }

}

/*******************************************************************************
 * Copyright (c) 2008 IBM Corporation and Others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Kentarou FUKUDA - initial API and implementation
 *******************************************************************************/

class TreeWalkerImpl implements TreeWalker {

  private Node walkerRoot;
  private Node current;
  private int whatToShow;
  private NodeFilter filter;
  private NodeFilter defaultFilter;
  private boolean entitiyReferenceExpansion;
  private boolean noFilter = true;

  public TreeWalkerImpl(Node root, int whatToShow, NodeFilter filter,
      boolean entityReferenceExpansion) throws DOMException {
    if (null == root) {
      throw new DOMException(DOMException.NOT_SUPPORTED_ERR,
          "Root can't be a null.");
    }
    this.walkerRoot = root;
    this.current = root;
    this.whatToShow = whatToShow;
    this.filter = filter;
    this.noFilter = (null == filter);
    this.entitiyReferenceExpansion = entityReferenceExpansion;
    this.defaultFilter = new WhatToShowNodeFilter(whatToShow);
  }

  private short eval(Node target) {
    short flag = defaultFilter.acceptNode(target);

    // If the node is skipped by whatToShow flag, a NodeFiilter will not be
    // called.
    if (noFilter || flag == NodeFilter.FILTER_SKIP) {
      return flag;
    }
    return filter.acceptNode(target);
  }

  private Node getVisibleNextSibling(Node target, Node root) {
    if (target == root) {
      return null;
    }
    Node tmpN = target.getNextSibling();
    if (null == tmpN) {
      Node tmpP = target.getParentNode();
      if (eval(tmpP) == NodeFilter.FILTER_SKIP) {
        return getVisibleNextSibling(tmpP, root);
      }
      return null;
    }
    switch (eval(tmpN)) {
    case NodeFilter.FILTER_ACCEPT:
      return tmpN;
    case NodeFilter.FILTER_SKIP:
      Node tmpC = getVisibleFirstChild(tmpN);
      if (null != tmpC) {
        return tmpC;
      }
      // case NodeFilter.FILTER_REJECT:
    default:
      return getVisibleNextSibling(tmpN, root);
    }
  }

  private Node getVisiblePreviousSibling(Node target, Node root) {
    if (target == root) {
      return null;
    }
    Node tmpN = target.getPreviousSibling();
    if (null == tmpN) {
      Node tmpP = target.getParentNode();
      if (eval(tmpP) == NodeFilter.FILTER_SKIP) {
        return getVisiblePreviousSibling(tmpP, root);
      }
      return null;
    }
    switch (eval(tmpN)) {
    case NodeFilter.FILTER_ACCEPT:
      return tmpN;
    case NodeFilter.FILTER_SKIP:
      Node tmpC = getVisibleLastChild(tmpN);
      if (null != tmpC) {
        return tmpC;
      }
      // case NodeFilter.FILTER_REJECT:
    default:
      return getVisiblePreviousSibling(tmpN, root);
    }
  }

  private Node getVisibleFirstChild(Node target) {
    if (!entitiyReferenceExpansion
        && Node.ENTITY_REFERENCE_NODE == target.getNodeType()) {
      return null;
    }
    Node tmpN = target.getFirstChild();
    if (null == tmpN) {
      return null;
    }

    switch (eval(tmpN)) {
    case NodeFilter.FILTER_ACCEPT:
      return tmpN;
    case NodeFilter.FILTER_SKIP:
      Node tmpN2 = getVisibleFirstChild(tmpN);
      if (null != tmpN2) {
        return tmpN2;
      }
      // case NodeFilter.FILTER_REJECT:
    default:
      return getVisibleNextSibling(tmpN, target);
    }
  }

  private Node getVisibleLastChild(Node target) {
    if (!entitiyReferenceExpansion
        && Node.ENTITY_REFERENCE_NODE == target.getNodeType()) {
      return null;
    }
    Node tmpN = target.getLastChild();
    if (null == tmpN) {
      return null;
    }

    switch (eval(tmpN)) {
    case NodeFilter.FILTER_ACCEPT:
      return tmpN;
    case NodeFilter.FILTER_SKIP:
      Node tmpN2 = getVisibleLastChild(tmpN);
      if (null != tmpN2) {
        return tmpN2;
      }
      // case NodeFilter.FILTER_REJECT:
    default:
      return getVisiblePreviousSibling(tmpN, target);
    }
  }

  private Node getVisibleParent(Node target) {
    if (target == walkerRoot) {
      return null;
    }
    Node tmpN = target.getParentNode();
    if (null == tmpN) {
      return null;
    }
    switch (eval(tmpN)) {
    case NodeFilter.FILTER_ACCEPT:
      return tmpN;
      // case NodeFilter.FILTER_SKIP:
      // case NodeFilter.FILTER_REJECT:
    default:
      return getVisibleParent(tmpN);
    }
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#firstChild()
   */
  public Node firstChild() {
    Node result = getVisibleFirstChild(current);
    if (null != result) {
      current = result;
    }
    return result;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#getCurrentNode()
   */
  public Node getCurrentNode() {
    return current;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#getExpandEntityReferences()
   */
  public boolean getExpandEntityReferences() {
    return entitiyReferenceExpansion;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#getFilter()
   */
  public NodeFilter getFilter() {
    return filter;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#getRoot()
   */
  public Node getRoot() {
    return walkerRoot;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#getWhatToShow()
   */
  public int getWhatToShow() {
    return whatToShow;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#lastChild()
   */
  public Node lastChild() {
    Node result = getVisibleLastChild(current);
    if (null != result) {
      current = result;
    }
    return result;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#nextNode()
   */
  public Node nextNode() {
    // search child
    Node tmpN = getVisibleFirstChild(current);
    if (null != tmpN) {
      current = tmpN;
      return tmpN;
    }

    // search sibling
    tmpN = getVisibleNextSibling(current, walkerRoot);
    if (null != tmpN) {
      current = tmpN;
      return tmpN;
    }

    // search parent's sibling
    Node tmpP = getVisibleParent(current);
    while (null != tmpP) {
      tmpN = getVisibleNextSibling(tmpP, walkerRoot);
      if (null != tmpN) {
        current = tmpN;
        return tmpN;
      } else {
        tmpP = getVisibleParent(tmpP);
      }
    }
    return null;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#nextSibling()
   */
  public Node nextSibling() {
    Node result = getVisibleNextSibling(current, walkerRoot);
    if (null != result) {
      current = result;
    }
    return result;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#parentNode()
   */
  public Node parentNode() {
    Node result = getVisibleParent(current);
    if (null != result) {
      current = result;
    }
    return result;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#previousNode()
   */
  public Node previousNode() {
    // search previous sibling
    Node tmpN = getVisiblePreviousSibling(current, walkerRoot);
    // no sibling, search parent
    if (null == tmpN) {
      tmpN = getVisibleParent(current);
      if (null != tmpN) {
        current = tmpN;
        return tmpN;
      }
      return null;
    }

    // search last child of previous sibling
    Node tmpC = getVisibleLastChild(tmpN);
    while (null != tmpC) {
      tmpN = tmpC;
      tmpC = getVisibleLastChild(tmpN);
    }
    if (null != tmpN) {
      current = tmpN;
      return tmpN;
    }

    return null;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#previousSibling()
   */
  public Node previousSibling() {
    Node result = getVisiblePreviousSibling(current, walkerRoot);
    if (null != result) {
      current = result;
    }
    return result;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.TreeWalker#setCurrentNode(org.w3c.dom.Node)
   */
  public void setCurrentNode(Node arg0) {
    if (arg0 == null) {
      System.out.println("Current node can't be null.");
    }
    current = arg0;
  }

}
/*******************************************************************************
 * Copyright (c) 2008 IBM Corporation and Others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Kentarou FUKUDA - initial API and implementation
 *******************************************************************************/
 class WhatToShowNodeFilter implements NodeFilter {

  private int filter;

  public WhatToShowNodeFilter(int whatToShow) {
    this.filter = whatToShow;
  }

  /*
   * (non-Javadoc)
   * 
   * @see org.w3c.dom.traversal.NodeFilter#acceptNode(org.w3c.dom.Node)
   */
  public short acceptNode(Node arg0) {
    if (null == arg0) {
      return FILTER_REJECT;
    }

    if ((filter & (1 << (arg0.getNodeType() - 1))) != 0) {
      return FILTER_ACCEPT;
    }
    return FILTER_SKIP;
  }
}

   
    
    
  








Related examples in the same category

1.Copy an XML document
2.Create DOM Document out of string
3.Create Document with root QName
4.Create Empty DOM Document
5.Displays a DOM document in a tree control.
6.New Document From InputStream
7.New Document From String
8.load Document by element
9.load Document from InputStream
10.get Document Element from a file
11.Start a new XML Document
12.Document To String
13.Return a new document, ready to populate
14.Read Xml from InputStream and return Document
15.Read Xml from Reader and return Document
16.Gets the owner document of a node.
17.Creates an element on the given document.
18.Loads a W3C XML document from a file.
19.Your Own XML Reader