Java/XML/DOM Tree

Материал из Java эксперт
Версия от 07:16, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Accessing different types of DOM tree nodes

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.CharacterData;
import org.w3c.dom.rument;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.parse("sample.xml");
    Element purchaseOrder = document.getDocumentElement();
    printElement(purchaseOrder, "");
  }
  static void printElement(Element element, String indent) {
    System.out.println("Element "" + element.getNodeName() + """);
    NodeList children = element.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
      Node child = children.item(i);
      switch (child.getNodeType()) {
      case Node.ELEMENT_NODE:
        printElement((Element) child, indent + "\t");
        break;
      case Node.ATTRIBUTE_NODE:
        Attr attr = (Attr) child;
        System.out.println("\tAttribute: "" + attr.getName() + "" = "" + attr.getValue() + """);
        break;
      case Node.ruMENT_NODE:
        Comment comment = (Comment) child;
        System.out.println("\tComment: "" + comment.getData() + """);
        break;
      case Node.CDATA_SECTION_NODE:
        CharacterData cdata = (CharacterData) child;
        System.out.println("\tCDatat: "" + cdata.getData() + """);
        break;
      case Node.TEXT_NODE:
        Text text = (Text) child;
        System.out.println("\tText: "" + text.getData() + """);
        break;
      default:
        System.out.println("\tUnknown node type: "" + child.getNodeType() + """);
        break;
      }
    }
  }
}





Copying a Subtree of Nodes from One DOM Document to Another

     

import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setExpandEntityReferences(false);
    Document doc1 = factory.newDocumentBuilder().parse(new File("filename"));
    NodeList list = doc1.getElementsByTagName("entry");
    Element element = (Element) list.item(0);
    Document doc2 = factory.newDocumentBuilder().parse(new File("infilename2.xml"));
    Node dup = doc2.importNode(element, true);
    doc2.getDocumentElement().appendChild(dup);
  }
}





Copying a Subtree of Nodes in a DOM Document

     

import java.io.File;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(true);
    factory.setExpandEntityReferences(false);
    Document doc = factory.newDocumentBuilder().parse(new File("filename"));
    NodeList list = doc.getElementsByTagName("entry");
    Element element = (Element) list.item(0);
    Element dup = (Element) element.cloneNode(true);
    element.getParentNode().insertBefore(dup, element.getNextSibling());
  }
}





Create new DOM tree with fully qualified element names

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.newDocument();
    String docNS = "http://www.my-company.ru";
    Element order = document.createElementNS(docNS, "order");
    document.appendChild(order);
    order.setAttribute("xmlns", docNS);
  }
}





Creating a new DOM tree

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.newDocument();
    Element root = document.createElement("order");
    document.appendChild(root);
  }
}





DOM Util: get Child Text

  
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Main {
  public static String getChildText(Element parent, String childName) {
    NodeList list = parent.getElementsByTagName(childName);
    if (list.getLength() > 1) {
      throw new IllegalStateException("Multiple child elements with name " + childName);
    } else if (list.getLength() == 0) {
      return null;
    }
    Element child = (Element) list.item(0);
    return getText(child);
  }
  public static String getText(Element element) {
    StringBuffer buf = new StringBuffer();
    NodeList list = element.getChildNodes();
    boolean found = false;
    for (int i = 0; i < list.getLength(); i++) {
      Node node = list.item(i);
      if (node.getNodeType() == Node.TEXT_NODE) {
        buf.append(node.getNodeValue());
        found = true;
      }
    }
    return found ? buf.toString() : null;
  }
}





Get Child Content

  
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Main {
  public static String getChildContent(Element parent, String name, String missing, String empty) {
    Element child = getChild(parent, name);
    if (child == null) {
      return missing;
    } else {
      String content = (String) getContent(child);
      return (content != null) ? content : empty;
    }
  }
  public static Object getContent(Element element) {
    NodeList nl = element.getChildNodes();
    StringBuffer content = new StringBuffer();
    for (int i = 0; i < nl.getLength(); i++) {
      Node node = nl.item(i);
      switch (node.getNodeType()) {
      case Node.ELEMENT_NODE:
        return node;
      case Node.CDATA_SECTION_NODE:
      case Node.TEXT_NODE:
        content.append(node.getNodeValue());
        break;
      }
    }
    return content.toString().trim();
  }
  public static Element getChild(Element parent, String name) {
    for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (child instanceof Element && name.equals(child.getNodeName())) {
        return (Element) child;
      }
    }
    return null;
  }
}





Gets the child of the specified element having the specified name. If the child with this name doesn"t exist then null is returned instead.

   
import java.util.ArrayList;
import java.util.Iterator;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * A utility class to cover up the rough bits of xml parsing
 * 
 * @author 
 * @version $Revision: 2787 $
 */
@SuppressWarnings("unchecked")
public class XmlHelper {
  /**
   * Returns an iterator over the children of the given element with the given
   * tag name.
   * 
   * @param element
   *          The parent element
   * @param tagName
   *          The name of the desired child
   * @return An interator of children or null if element is null.
   */
  public static Iterator getChildrenByTagName(Element element, String tagName) {
    if (element == null)
      return null;
    // getElementsByTagName gives the corresponding elements in the whole
    // descendance. We want only children
    NodeList children = element.getChildNodes();
    ArrayList goodChildren = new ArrayList();
    for (int i = 0; i < children.getLength(); i++) {
      Node currentChild = children.item(i);
      if (currentChild.getNodeType() == Node.ELEMENT_NODE
          && ((Element) currentChild).getTagName().equals(tagName)) {
        goodChildren.add(currentChild);
      }
    }
    return goodChildren.iterator();
  }
  /**
   * Gets the child of the specified element having the specified unique name.
   * If there are more than one children elements with the same name and
   * exception is thrown.
   * 
   * @param element
   *          The parent element
   * @param tagName
   *          The name of the desired child
   * @return The named child.
   * 
   * @throws Exception
   *           Child was not found or was not unique.
   */
  public static Element getUniqueChild(Element element, String tagName) throws Exception {
    Iterator goodChildren = getChildrenByTagName(element, tagName);
    if (goodChildren != null && goodChildren.hasNext()) {
      Element child = (Element) goodChildren.next();
      if (goodChildren.hasNext()) {
        throw new Exception("expected only one " + tagName + " tag");
      }
      return child;
    } else {
      throw new Exception("expected one " + tagName + " tag");
    }
  }
  /**
   * Gets the child of the specified element having the specified name. If the
   * child with this name doesn"t exist then null is returned instead.
   * 
   * @param element
   *          the parent element
   * @param tagName
   *          the name of the desired child
   * @return either the named child or null
   * @throws Exception
   */
  public static Element getOptionalChild(Element element, String tagName) throws Exception {
    return getOptionalChild(element, tagName, null);
  }
  /**
   * Gets the child of the specified element having the specified name. If the
   * child with this name doesn"t exist then the supplied default element is
   * returned instead.
   * 
   * @param element
   *          the parent element
   * @param tagName
   *          the name of the desired child
   * @param defaultElement
   *          the element to return if the child doesn"t exist
   * @return either the named child or the supplied default
   * @throws Exception
   */
  public static Element getOptionalChild(Element element, String tagName, Element defaultElement)
      throws Exception {
    Iterator goodChildren = getChildrenByTagName(element, tagName);
    if (goodChildren != null && goodChildren.hasNext()) {
      Element child = (Element) goodChildren.next();
      if (goodChildren.hasNext()) {
        throw new Exception("expected only one " + tagName + " tag");
      }
      return child;
    } else {
      return defaultElement;
    }
  }
  /**
   * Get the content of the given element.
   * 
   * @param element
   *          The element to get the content for.
   * @return The content of the element or null.
   * @throws Exception
   */
  public static String getElementContent(final Element element) throws Exception {
    return getElementContent(element, null);
  }
  /**
   * Get the content of the given element.
   * 
   * @param element
   *          The element to get the content for.
   * @param defaultStr
   *          The default to return when there is no content.
   * @return The content of the element or the default.
   * @throws Exception
   */
  public static String getElementContent(Element element, String defaultStr) throws Exception {
    if (element == null)
      return defaultStr;
    NodeList children = element.getChildNodes();
    String result = "";
    for (int i = 0; i < children.getLength(); i++) {
      if (children.item(i).getNodeType() == Node.TEXT_NODE
          || children.item(i).getNodeType() == Node.CDATA_SECTION_NODE) {
        result += children.item(i).getNodeValue();
      } else if (children.item(i).getNodeType() == Node.ruMENT_NODE) {
        // Ignore comment nodes
      }
    }
    return result.trim();
  }
  /**
   * Macro to get the content of a unique child element.
   * 
   * @param element
   *          The parent element.
   * @param tagName
   *          The name of the desired child.
   * @return The element content or null.
   * @throws Exception
   */
  public static String getUniqueChildContent(Element element, String tagName) throws Exception {
    return getElementContent(getUniqueChild(element, tagName));
  }
  /**
   * Macro to get the content of an optional child element.
   * 
   * @param element
   *          The parent element.
   * @param tagName
   *          The name of the desired child.
   * @return The element content or null.
   * @throws Exception
   */
  public static String getOptionalChildContent(Element element, String tagName) throws Exception {
    return getElementContent(getOptionalChild(element, tagName));
  }
  public static boolean getOptionalChildBooleanContent(Element element, String name)
      throws Exception {
    Element child = getOptionalChild(element, name);
    if (child != null) {
      String value = getElementContent(child).toLowerCase();
      return value.equals("true") || value.equals("yes");
    }
    return false;
  }
}





Gets the child of the specified element having the specified unique name

   
import java.util.ArrayList;
import java.util.Iterator;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * A utility class to cover up the rough bits of xml parsing
 * 
 * @author 
 * @version $Revision: 2787 $
 */
@SuppressWarnings("unchecked")
public class XmlHelper {
  /**
   * Returns an iterator over the children of the given element with the given
   * tag name.
   * 
   * @param element
   *          The parent element
   * @param tagName
   *          The name of the desired child
   * @return An interator of children or null if element is null.
   */
  public static Iterator getChildrenByTagName(Element element, String tagName) {
    if (element == null)
      return null;
    // getElementsByTagName gives the corresponding elements in the whole
    // descendance. We want only children
    NodeList children = element.getChildNodes();
    ArrayList goodChildren = new ArrayList();
    for (int i = 0; i < children.getLength(); i++) {
      Node currentChild = children.item(i);
      if (currentChild.getNodeType() == Node.ELEMENT_NODE
          && ((Element) currentChild).getTagName().equals(tagName)) {
        goodChildren.add(currentChild);
      }
    }
    return goodChildren.iterator();
  }
  /**
   * Gets the child of the specified element having the specified unique name.
   * If there are more than one children elements with the same name and
   * exception is thrown.
   * 
   * @param element
   *          The parent element
   * @param tagName
   *          The name of the desired child
   * @return The named child.
   * 
   * @throws Exception
   *           Child was not found or was not unique.
   */
  public static Element getUniqueChild(Element element, String tagName) throws Exception {
    Iterator goodChildren = getChildrenByTagName(element, tagName);
    if (goodChildren != null && goodChildren.hasNext()) {
      Element child = (Element) goodChildren.next();
      if (goodChildren.hasNext()) {
        throw new Exception("expected only one " + tagName + " tag");
      }
      return child;
    } else {
      throw new Exception("expected one " + tagName + " tag");
    }
  }
  /**
   * Gets the child of the specified element having the specified name. If the
   * child with this name doesn"t exist then null is returned instead.
   * 
   * @param element
   *          the parent element
   * @param tagName
   *          the name of the desired child
   * @return either the named child or null
   * @throws Exception
   */
  public static Element getOptionalChild(Element element, String tagName) throws Exception {
    return getOptionalChild(element, tagName, null);
  }
  /**
   * Gets the child of the specified element having the specified name. If the
   * child with this name doesn"t exist then the supplied default element is
   * returned instead.
   * 
   * @param element
   *          the parent element
   * @param tagName
   *          the name of the desired child
   * @param defaultElement
   *          the element to return if the child doesn"t exist
   * @return either the named child or the supplied default
   * @throws Exception
   */
  public static Element getOptionalChild(Element element, String tagName, Element defaultElement)
      throws Exception {
    Iterator goodChildren = getChildrenByTagName(element, tagName);
    if (goodChildren != null && goodChildren.hasNext()) {
      Element child = (Element) goodChildren.next();
      if (goodChildren.hasNext()) {
        throw new Exception("expected only one " + tagName + " tag");
      }
      return child;
    } else {
      return defaultElement;
    }
  }
  /**
   * Get the content of the given element.
   * 
   * @param element
   *          The element to get the content for.
   * @return The content of the element or null.
   * @throws Exception
   */
  public static String getElementContent(final Element element) throws Exception {
    return getElementContent(element, null);
  }
  /**
   * Get the content of the given element.
   * 
   * @param element
   *          The element to get the content for.
   * @param defaultStr
   *          The default to return when there is no content.
   * @return The content of the element or the default.
   * @throws Exception
   */
  public static String getElementContent(Element element, String defaultStr) throws Exception {
    if (element == null)
      return defaultStr;
    NodeList children = element.getChildNodes();
    String result = "";
    for (int i = 0; i < children.getLength(); i++) {
      if (children.item(i).getNodeType() == Node.TEXT_NODE
          || children.item(i).getNodeType() == Node.CDATA_SECTION_NODE) {
        result += children.item(i).getNodeValue();
      } else if (children.item(i).getNodeType() == Node.ruMENT_NODE) {
        // Ignore comment nodes
      }
    }
    return result.trim();
  }
  /**
   * Macro to get the content of a unique child element.
   * 
   * @param element
   *          The parent element.
   * @param tagName
   *          The name of the desired child.
   * @return The element content or null.
   * @throws Exception
   */
  public static String getUniqueChildContent(Element element, String tagName) throws Exception {
    return getElementContent(getUniqueChild(element, tagName));
  }
  /**
   * Macro to get the content of an optional child element.
   * 
   * @param element
   *          The parent element.
   * @param tagName
   *          The name of the desired child.
   * @return The element content or null.
   * @throws Exception
   */
  public static String getOptionalChildContent(Element element, String tagName) throws Exception {
    return getElementContent(getOptionalChild(element, tagName));
  }
  public static boolean getOptionalChildBooleanContent(Element element, String name)
      throws Exception {
    Element child = getOptionalChild(element, name);
    if (child != null) {
      String value = getElementContent(child).toLowerCase();
      return value.equals("true") || value.equals("yes");
    }
    return false;
  }
}





Get the first child of the specified type.

  
import org.w3c.dom.Node;
public class Utils {
  /**
   * Get the first child of the specified type.
   * 
   * @param parent
   * @param type
   * @return
   */
  public static Node getChild(Node parent, int type) {
      Node n = parent.getFirstChild();
      while (n != null && type != n.getNodeType()) {
          n = n.getNextSibling();
      }
      if (n == null) {
          return null;
      }
      return n;
  }

}





Get the first child"s content ( ie it"s included TEXT node ).

  
import org.w3c.dom.Node;
/**
 *  
 *
 * @author Costin Manolache
 */
public class Main {
  /** Get the first child"s content ( ie it"s included TEXT node ).
   */
  public static String getChildContent( Node parent, String name ) {
      Node first=parent.getFirstChild();
      if( first==null ) return null;
      for (Node node = first; node != null;
           node = node.getNextSibling()) {
          //System.out.println("getNode: " + name + " " + node.getNodeName());
          if( name.equals( node.getNodeName() ) ) {
              return getContent( node );
          }
      }
      return null;
  }
  /** Get the trimed text content of a node or null if there is no text
   */
  public static String getContent(Node n ) {
      if( n==null ) return null;
      Node n1=getChild(n, Node.TEXT_NODE);
      if( n1==null ) return null;
      String s1=n1.getNodeValue();
      return s1.trim();
  }
  /** Get the first direct child with a given type
   */
  public static Node getChild( Node parent, int type ) {
      Node n=parent.getFirstChild();
      while( n!=null && type != n.getNodeType() ) {
          n=n.getNextSibling();
      }
      if( n==null ) return null;
      return n;
  }
}





Get the first direct child with a given type

  
import org.w3c.dom.Node;
/**
 *  
 *
 * @author Costin Manolache
 */
public class Main {

  /** Get the first direct child with a given type
   */
  public static Node getChild( Node parent, int type ) {
      Node n=parent.getFirstChild();
      while( n!=null && type != n.getNodeType() ) {
          n=n.getNextSibling();
      }
      if( n==null ) return null;
      return n;
  }
}





Get this Document"s root node

   
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class Main {
  // return this Document"s root node
  public static Element getRoot(Document doc) {
      return doc.getDocumentElement();
  } // getRoot(Document(:  Element
  
 
}





Manipulate w3c DOM trees

   
// 
// Copyright 2007 Requea.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at 
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Stack;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
 * Utilities to manipulate w3c DOM trees.
 * @author Pierre Dubois
 */
public class XMLUtils {
    private static DocumentBuilderFactory fDocumentFactory;
    private static Stack fParsersPool = new Stack();
    /**
     * Public Id and the Resource path (of the cached copy) 
     * of the DTDs for tag library descriptors. 
     */
    public static final String TAGLIB_DTD_PUBLIC_ID_11 = 
  "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN";
    public static final String TAGLIB_DTD_RESOURCE_PATH_11 = 
  "/javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd";
    public static final String TAGLIB_DTD_PUBLIC_ID_12 = 
  "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN";
    public static final String TAGLIB_DTD_RESOURCE_PATH_12 = 
  "/javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd";
    /**
     * Public Id and the Resource path (of the cached copy) 
     * of the DTDs for web application deployment descriptors
     */
    public static final String WEBAPP_DTD_PUBLIC_ID_22 = 
  "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN";
    public static final String WEBAPP_DTD_RESOURCE_PATH_22 = 
  "/javax/servlet/resources/web-app_2_2.dtd";
    public static final String WEBAPP_DTD_PUBLIC_ID_23 = 
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN";
    public static final String WEBAPP_DTD_RESOURCE_PATH_23 = 
  "/javax/servlet/resources/web-app_2_3.dtd";
    /**
     * List of the Public IDs that we cache, and their
     * associated location. This is used by 
     * an EntityResolver to return the location of the
     * cached copy of a DTD.
     */
    public static final String[] CACHED_DTD_PUBLIC_IDS = {
  TAGLIB_DTD_PUBLIC_ID_11,
  TAGLIB_DTD_PUBLIC_ID_12,
  WEBAPP_DTD_PUBLIC_ID_22,
  WEBAPP_DTD_PUBLIC_ID_23,
    };
    public static final String[] CACHED_DTD_RESOURCE_PATHS = {
  TAGLIB_DTD_RESOURCE_PATH_11,
  TAGLIB_DTD_RESOURCE_PATH_12,
  WEBAPP_DTD_RESOURCE_PATH_22,
  WEBAPP_DTD_RESOURCE_PATH_23,
    };

    private static synchronized void initFactory() {
      if(fDocumentFactory != null) 
        return;
      
      fDocumentFactory =
            DocumentBuilderFactory.newInstance();
      fDocumentFactory.setNamespaceAware(true);
      fDocumentFactory.setIgnoringElementContentWhitespace(true);
      fDocumentFactory.setValidating(false);
    }
    
    public static synchronized DocumentBuilder getParser() throws ParserConfigurationException {
      if(fParsersPool.isEmpty()) {
        // create a new parser
        initFactory();
        DocumentBuilder builder = fDocumentFactory.newDocumentBuilder();
            builder.setEntityResolver(entityResolver);
        return builder;
      } else {
        return (DocumentBuilder)fParsersPool.pop();
      }
    }
    public static synchronized void releaseParser(DocumentBuilder parser) {
      if(parser != null)
          fParsersPool.push(parser);
    }
    
    /**
     * Parse an xml document as an imput stream.
     * @param is
     * @return
     * @throws XMLException
     */
    public static Document parse(InputStream is) {
      DocumentBuilder builder = null;
      try {
        builder = getParser();
          // parse the document
              Document doc = builder.parse(is);
              return doc;
        } catch (Exception e) {
            
        } finally {
        releaseParser(builder);
        }
    }
    /**
     * Parses an xml document as a string.
     * @param xml
     * @return
     * @throws XMLException
     */
    public static Document parse(String xml) {
      DocumentBuilder builder = null;
      try {
        builder = getParser();
          // parse the document
          try {
              InputStream is = new ByteArrayInputStream(xml.getBytes());
              Document doc = builder.parse(is);
              return doc;
          } catch (SAXException e) {    
              
          } catch (IOException e) {
               
          }
        } catch (ParserConfigurationException e) {
            
        } finally {
        releaseParser(builder);
      }
    }

    /**
     * Creates a new and empty document.
     * @return
     */
    public static Document newDocument() {
      DocumentBuilder builder = null;
      try {
        builder = getParser();
            return builder.newDocument();
      } catch (ParserConfigurationException e) {
          throw new RuntimeException(e);
      } finally {
      releaseParser(builder);
    }
    }
    /**
     * Creates a new document with a document root element.
     * @param name
     * @return
     */
    public static Element newElement(String name) {
      DocumentBuilder builder = null;
      try {
        builder = getParser();
            Document doc = builder.newDocument();
            Element el = doc.createElement(name);
            doc.appendChild(el);
            return el;
      } catch (ParserConfigurationException e) {
          throw new RuntimeException(e);
      } finally {
      releaseParser(builder);
    }
    }
    /**
     * Serialize an element to a string.
     * @param element
     * @return
     * @throws XMLException 
     */
    public static String ElementToString(Element element) {
        return privateElementToString(element, true, true);
    }
    public static String ElementToString(Element element, boolean pretty) {
        return privateElementToString(element, true, pretty);
    }
    /**
     * Serialize a document to a string
     * @param doc
     * @return
     */
    public static String DocumentToString(Document doc)  {
        return privateElementToString(doc.getDocumentElement(), false, true);
    }
    public static String DocumentToString(Document doc, boolean pretty) {
        return privateElementToString(doc.getDocumentElement(), false, pretty);
    }
    /**
     * Get the first child element to match a given name. 
     * Look for a child element in the same namespace as the parent.
     * 
     * @param parent
     * @param name
     * @return
     */
    public static Element getChild(Element parent, String name) {
      Element child = getFirstChild(parent);
      while(child != null) {
          String tagName = child.getTagName(); 
        if(tagName != null && tagName.equals(name)) {
          return child;
        }
        if(child.getPrefix() != null && child.getPrefix().equals(parent.getPrefix()) && child.getLocalName() != null && child.getLocalName().equals(name)) {
          return child;
        }
        child = getNext(child);
      }
      return child;
    }
    /**
     * Get the first child element to match a given name. 
     * Look for a child element in the same namespace as the parent.
     * 
     * @param parent
     * @param name
     * @return
     */
    public static Element getChild(Element parent, String ns, String name) {
      Element child = getFirstChild(parent);
      while(child != null) {
        if(child.getLocalName().equals(name)) {
          if(ns == null && child.getNamespaceURI() == null) {
            return child;
          } else if(ns != null && ns.equals(child.getNamespaceURI())) {
              return child;
          }
        }
        child = getNext(child);
      }
      return child;
    }
    /**
     * Get the first child element of an element.
     * @param el
     * @return
     */
    public static Element getFirstChild(Element el) {
      if(el == null) {
        return null;
      }
        NodeList lst = el.getChildNodes();
        int len = lst.getLength();
        for (int i = 0; i < len; i++) {
            Node n = lst.item(i);
            if (n instanceof Element)
                return (Element) n;
        }
        return null;
    }
    
    /**
     * Get the next sibling element of a given element.
     * @param el
     * @return
     */
    public static Element getNext(Element el) {
        Node n = el.getNextSibling();
        while (n != null && !(n instanceof Element)) {
            // get the next one
            n = n.getNextSibling();
        }
        if (n instanceof Element) {
            return (Element) n;
        }
        // else, nothing to return
        return null;
    }
    /**
     * Get the next sibling element of a given element.
     * @param el
     * @return
     */
    public static Element getNextSibling(Element el) {
      String tagName = el.getTagName();
      if(tagName == null) {
        return null;
      }
      Node n = el.getNextSibling();
        while (n != null && (
            !(n instanceof Element) || 
            !tagName.equals(((Element)n).getTagName()))) {
            // get the next one
            n = n.getNextSibling();
        }
        if (n instanceof Element) {
            return (Element) n;
        } else {
          // else, nothing to return
          return null;
        }
    }
    /**
     * Get the previous sibling element of a given element.
     * @param el
     * @return
     */
    public static Element getPrevious(Element el) {
        Node n = el.getPreviousSibling();
        while (n != null && !(n instanceof Element)) {
            // get the next one
            n = n.getPreviousSibling();
        }
        if (n instanceof Element) {
            return (Element) n;
        } else {
          // else, nothing to return
          return null;
        }
    }
    /**
     * Get the previous sibling element of a given element.
     * @param el
     * @return
     */
    public static Element getPreviousSibling(Element el) {
        Node n = el.getPreviousSibling();
        while (n != null && ( 
            !(n instanceof Element) || 
            !el.getTagName().equals(((Element)n).getTagName()))) {
            // get the next one
            n = n.getPreviousSibling();
        }
        if (n instanceof Element) {
            return (Element) n;
        } else {
          // else, nothing to return
          return null;
        }
    }
    /**
     * Returns the text value of an element.
     * @param el
     * @return
     */
    public static String getTextValue(Element el) {
        StringBuffer b = new StringBuffer();
        // retrieve the text node child
        NodeList nl = el.getChildNodes();
        int len = nl.getLength();
        for (int i = 0; i < len; i++) {
            Node n = nl.item(i);
            if (n instanceof Text) {
                Text t = (Text) n;
                b.append(t.getData());
            }
        }
        // trim the result, ignoring the first spaces and cariage return
        int iFirst =0;
        for(; iFirst<b.length(); iFirst++) {
          char c = b.charAt(iFirst);
          if(c != " " && c != "\r" && c != "\n" && c != "\t") {
            break;
          }
        }
        // start by the end as well
        int iLast = b.length()-1; 
        for(; iLast>=0; iLast--) {
          char c = b.charAt(iLast);
          if(c != " " && c != "\r" && c != "\n" && c != "\t") {
            break;
          }
        }
        return b.substring(iFirst, iLast+1);
    }
    /**
     * Get the text value of a child element with a given name. 
     * @param parent
     * @param name
     * @return
     */
    public static String getChildText(Element parent, String name) {
        Element child = getChild(parent, name);
        if (child != null) {
            return getTextValue(child);
        }
        return null;
    }
    /**
     * Get the text value of a child element with a given name. 
     * @param parent
     * @param name
     * @return
     */
    public static String getChildText(Element parent, String ns, String name) {
        Element child = getChild(parent, ns, name);
        if (child != null) {
            return getTextValue(child);
        }
        return null;
    }
    /**
     * Adds an element as a child of a given element. 
     * The child is created with the same namespace as the parent. 
     * @param parent
     * @param name
     * @return
     */
    public static Element addElement(Element parent, String name) {
        Document doc = parent.getOwnerDocument();
        String qname;
        if(parent.getPrefix() != null) {
            qname = parent.getPrefix() + ":" + name;
        } else {
            qname = name;
        }
        Element child = doc.createElementNS(parent.getNamespaceURI(), qname);
        parent.appendChild(child);
        return child;
    }
    /**
     * Adds an element as a child of a given element and sets the text value.
     * The child is created with the same namespace as the parent. 
     * 
     * @param parent
     * @param name
     * @param textValue
     * @return
     */
    public static Element addElement(
        Element parent,
        String name,
        String textValue) {
        
        Element child = addElement(parent, name);
        // create a text node
        if(textValue == null) {
          textValue = "";
        }
        Text txt = child.getOwnerDocument().createTextNode(textValue);
        child.appendChild(txt);
        return child;
    }
    /**
     * Sets the text value for a given element.
     * @param el
     * @param value
     */
    public static void setText(Element el, String value) {
        // remove the children if already exist
        while (el.getFirstChild() != null) {
            el.removeChild(el.getFirstChild());
        }
        if(value == null) {
          value = "";
        }
        Text txt = el.getOwnerDocument().createTextNode(value);
        el.appendChild(txt);
    }
    /**
     * Sets the text value for a given element as a CDATA section
     * @param el
     * @param value
     */
    public static void setCDATA(Element el, String value) {
        // remove the children if already exist
        while (el.getFirstChild() != null) {
            el.removeChild(el.getFirstChild());
        }
        if(value == null) {
          value = "";
        }
        CDATASection txt = el.getOwnerDocument().createCDATASection(value);
        el.appendChild(txt);
    }
    /**
     * Retrieve the namespace for a given prefix. 
     * Does a lookup into the parent hierarchy.
     * @param el
     * @param prefix
     * @return
     */
    public static String getNamespace(Element el, String prefix) {
        Element parent = el;
        while (parent != null) {
            String ns = parent.getAttribute("xmlns:" + prefix);
            if (ns != null && ns.length() > 0) {
                return ns;
            }
            // get the parent
            Node n = parent.getParentNode();
            if (n instanceof Element) {
                parent = (Element) n;
            } else {
                parent = null;
            }
        }
        // nothing found
        return null;
    }
    /*
     * serialize an element to a string.
     */
    private static String privateElementToString(
        Element element,
        boolean omitXMLDecl,
    boolean pretty)  {
      try {
        Source source = new DOMSource(element);
      StringWriter out = new StringWriter();
      
      StreamResult result = new StreamResult(out);
      Transformer xformer = TransformerFactory.newInstance().newTransformer();
      xformer.setOutputProperty("indent", "yes");
      xformer.transform(source, result);
      return out.toString();
      } catch(Exception e) {
       
      }
    }
    
  public static String getAttribute(Element el, String att) {
    String str = el.getAttribute(att);
    if(str == null || str.length() == 0) {
      return null;
    } else {
      return str;
    }
  }
  
    static EntityResolver entityResolver = new MyEntityResolver();
  static private class MyEntityResolver implements EntityResolver {

      public InputSource resolveEntity(String publicId, String systemId)
              throws SAXException {
          for (int i = 0; i < CACHED_DTD_PUBLIC_IDS.length; i++) {
              String cachedDtdPublicId = CACHED_DTD_PUBLIC_IDS[i];
              if (cachedDtdPublicId.equals(publicId)) {
                  String resourcePath = CACHED_DTD_RESOURCE_PATHS[i];
                  InputStream input = this.getClass().getResourceAsStream(
                          resourcePath);
                  if (input == null) {
                      throw new SAXException("file.not.found"+resourcePath);
                  }
                  InputSource isrc = new InputSource(input);
                  return isrc;
              }
          }
          return null;
      }
  }
}





Print Tree node

  
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/*
 * Copyright 2005 Joe Walker
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * 
 * @author Abey Mullassery
 * 
 */
public class Main {
  public static void printTree(Node doc) {
    if (doc == null) {
      System.out.println("Nothing to print!!");
      return;
    }
    try {
      System.out.println(doc.getNodeName() + "  " + doc.getNodeValue());
      NamedNodeMap cl = doc.getAttributes();
      for (int i = 0; i < cl.getLength(); i++) {
        Node node = cl.item(i);
        System.out.println(
          "\t" + node.getNodeName() + " ->" + node.getNodeValue());
      }
      NodeList nl = doc.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
        Node node = nl.item(i);
        printTree(node);
      }
    } catch (Throwable e) {
      System.out.println("Cannot print!! " + e.getMessage());
    }
  }
}





Reading a DOM tree from XML document

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.parse("sample.xml");
    Element tree = document.getDocumentElement();
  }
}





Returns an iterator over the children of the given element with the given tag name

   
import java.util.ArrayList;
import java.util.Iterator;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * A utility class to cover up the rough bits of xml parsing
 * 
 * @author 
 * @version $Revision: 2787 $
 */
@SuppressWarnings("unchecked")
public class XmlHelper {
  /**
   * Returns an iterator over the children of the given element with the given
   * tag name.
   * 
   * @param element
   *          The parent element
   * @param tagName
   *          The name of the desired child
   * @return An interator of children or null if element is null.
   */
  public static Iterator getChildrenByTagName(Element element, String tagName) {
    if (element == null)
      return null;
    // getElementsByTagName gives the corresponding elements in the whole
    // descendance. We want only children
    NodeList children = element.getChildNodes();
    ArrayList goodChildren = new ArrayList();
    for (int i = 0; i < children.getLength(); i++) {
      Node currentChild = children.item(i);
      if (currentChild.getNodeType() == Node.ELEMENT_NODE
          && ((Element) currentChild).getTagName().equals(tagName)) {
        goodChildren.add(currentChild);
      }
    }
    return goodChildren.iterator();
  }
  /**
   * Gets the child of the specified element having the specified unique name.
   * If there are more than one children elements with the same name and
   * exception is thrown.
   * 
   * @param element
   *          The parent element
   * @param tagName
   *          The name of the desired child
   * @return The named child.
   * 
   * @throws Exception
   *           Child was not found or was not unique.
   */
  public static Element getUniqueChild(Element element, String tagName) throws Exception {
    Iterator goodChildren = getChildrenByTagName(element, tagName);
    if (goodChildren != null && goodChildren.hasNext()) {
      Element child = (Element) goodChildren.next();
      if (goodChildren.hasNext()) {
        throw new Exception("expected only one " + tagName + " tag");
      }
      return child;
    } else {
      throw new Exception("expected one " + tagName + " tag");
    }
  }
  /**
   * Gets the child of the specified element having the specified name. If the
   * child with this name doesn"t exist then null is returned instead.
   * 
   * @param element
   *          the parent element
   * @param tagName
   *          the name of the desired child
   * @return either the named child or null
   * @throws Exception
   */
  public static Element getOptionalChild(Element element, String tagName) throws Exception {
    return getOptionalChild(element, tagName, null);
  }
  /**
   * Gets the child of the specified element having the specified name. If the
   * child with this name doesn"t exist then the supplied default element is
   * returned instead.
   * 
   * @param element
   *          the parent element
   * @param tagName
   *          the name of the desired child
   * @param defaultElement
   *          the element to return if the child doesn"t exist
   * @return either the named child or the supplied default
   * @throws Exception
   */
  public static Element getOptionalChild(Element element, String tagName, Element defaultElement)
      throws Exception {
    Iterator goodChildren = getChildrenByTagName(element, tagName);
    if (goodChildren != null && goodChildren.hasNext()) {
      Element child = (Element) goodChildren.next();
      if (goodChildren.hasNext()) {
        throw new Exception("expected only one " + tagName + " tag");
      }
      return child;
    } else {
      return defaultElement;
    }
  }
  /**
   * Get the content of the given element.
   * 
   * @param element
   *          The element to get the content for.
   * @return The content of the element or null.
   * @throws Exception
   */
  public static String getElementContent(final Element element) throws Exception {
    return getElementContent(element, null);
  }
  /**
   * Get the content of the given element.
   * 
   * @param element
   *          The element to get the content for.
   * @param defaultStr
   *          The default to return when there is no content.
   * @return The content of the element or the default.
   * @throws Exception
   */
  public static String getElementContent(Element element, String defaultStr) throws Exception {
    if (element == null)
      return defaultStr;
    NodeList children = element.getChildNodes();
    String result = "";
    for (int i = 0; i < children.getLength(); i++) {
      if (children.item(i).getNodeType() == Node.TEXT_NODE
          || children.item(i).getNodeType() == Node.CDATA_SECTION_NODE) {
        result += children.item(i).getNodeValue();
      } else if (children.item(i).getNodeType() == Node.ruMENT_NODE) {
        // Ignore comment nodes
      }
    }
    return result.trim();
  }
  /**
   * Macro to get the content of a unique child element.
   * 
   * @param element
   *          The parent element.
   * @param tagName
   *          The name of the desired child.
   * @return The element content or null.
   * @throws Exception
   */
  public static String getUniqueChildContent(Element element, String tagName) throws Exception {
    return getElementContent(getUniqueChild(element, tagName));
  }
  /**
   * Macro to get the content of an optional child element.
   * 
   * @param element
   *          The parent element.
   * @param tagName
   *          The name of the desired child.
   * @return The element content or null.
   * @throws Exception
   */
  public static String getOptionalChildContent(Element element, String tagName) throws Exception {
    return getElementContent(getOptionalChild(element, tagName));
  }
  public static boolean getOptionalChildBooleanContent(Element element, String name)
      throws Exception {
    Element child = getOptionalChild(element, name);
    if (child != null) {
      String value = getElementContent(child).toLowerCase();
      return value.equals("true") || value.equals("yes");
    }
    return false;
  }
}





Returns the concatenated child text of the specified node.

   
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
public class Main {
  
  /**
   * Returns the concatenated child text of the specified node.
   * This method only looks at the immediate children of type
   * Node.TEXT_NODE or the children of any child
   * node that is of type Node.CDATA_SECTION_NODE
   * for the concatenation.
   *
   * @param node The node to look at.
   */
  public static String getChildText(Node node) {
      
      // is there anything to do?
      if (node == null) {
          return null;
      }
      
      // concatenate children text
      StringBuffer str = new StringBuffer();
      Node child = node.getFirstChild();
      while (child != null) {
          short type = child.getNodeType();
          if (type == Node.TEXT_NODE) {
              str.append(child.getNodeValue());
          }
          else if (type == Node.CDATA_SECTION_NODE) {
              str.append(getChildText(child));
          }
          child = child.getNextSibling();
      }
      
      // return text value
      return str.toString();
      
  } // getChildText(Node):String
}





Return the next sibling with a given name and type

  
import org.w3c.dom.Node;
public class Main {
  /** 
   */ 
  public static Node getNext( Node current, String name, int type) {
      Node first=current.getNextSibling();
      if( first==null ) return null;
      for (Node node = first; node != null;
           node = node.getNextSibling()) {
          
          if( type >= 0 && node.getNodeType() != type ) continue;
          //System.out.println("getNode: " + name + " " + node.getNodeName());
          if( name==null )
              return node;
          if( name.equals( node.getNodeName() ) ) {
              return node;
          }
      }
      return null;
  }
}





Saving a DOM tree to XML file javax.xml.parsers (JAXP)

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.newDocument();
    Element order = document.createElement("order");
    document.appendChild(order);
    XMLSerializer serializer = new XMLSerializer();
    serializer.setOutputCharStream(new java.io.FileWriter("order.xml"));
    serializer.serialize(document);
  }
}





Search earlier siblings for a given node

  
/**********************************************************************************
*
* Copyright (c) 2003, 2004 The Regents of the University of Michigan, Trustees of Indiana University,
*                  Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation
*
* Licensed under the Educational Community License Version 1.0 (the "License");
* By obtaining, using and/or copying this Original Work, you agree that you have read,
* understand, and will comply with the terms and conditions of the Educational Community License.
* You may obtain a copy of the License at:
*
*      http://cvs.sakaiproject.org/licenses/license_1_0.html
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**********************************************************************************/
import org.w3c.dom.Node;
public class Utils {
  /**
   * Search earlier siblings for a given node
   * @param currentNode Starting point for our search
   * @param tagName Node name to look up
   * @return matching Node (null if none)
   */
  public static Node getPreviousSiblingByName(Node currentNode, String tagName) {
    Node node = currentNode.getPreviousSibling();
    while ((node != null) && (!node.getNodeName().equals(tagName))) {
      node = node.getPreviousSibling();
    }
    return node;
  }
}





Search for a named child of a given node

  
import org.w3c.dom.Node;
public class Utils {
  /**
   * Search for a named child of a given node
   * @param currentNode Starting point for our search
   * @param tagName Node name to look up
   * @return matching Node (null if none)
   */
  public static Node getChildSiblingByName(Node currentNode, String tagName) {
    Node node = currentNode.getFirstChild();
    while ((node != null) && (!node.getNodeName().equals(tagName))) {
      node = node.getNextSibling();
    }
    return node;
  }
}





Search our next siblings for a given node

  
/**********************************************************************************
*
* Copyright (c) 2003, 2004 The Regents of the University of Michigan, Trustees of Indiana University,
*                  Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation
*
* Licensed under the Educational Community License Version 1.0 (the "License");
* By obtaining, using and/or copying this Original Work, you agree that you have read,
* understand, and will comply with the terms and conditions of the Educational Community License.
* You may obtain a copy of the License at:
*
*      http://cvs.sakaiproject.org/licenses/license_1_0.html
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**********************************************************************************/

import org.w3c.dom.Node;
public class Utils {
  /**
   * Search our next siblings for a given node
   * @param currentNode Starting point for our search
   * @param tagName Node name to look up
   * @return matching Node (null if none)
   */
  public static Node getNextSiblingByName(Node currentNode, String tagName) {
    Node node = currentNode.getNextSibling();
    while ((node != null) && (!node.getNodeName().equals(tagName))) {
      node = node.getNextSibling();
    }
    return node;
  }
}





Search up the tree for a given node

  
/**********************************************************************************
*
* Copyright (c) 2003, 2004 The Regents of the University of Michigan, Trustees of Indiana University,
*                  Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation
*
* Licensed under the Educational Community License Version 1.0 (the "License");
* By obtaining, using and/or copying this Original Work, you agree that you have read,
* understand, and will comply with the terms and conditions of the Educational Community License.
* You may obtain a copy of the License at:
*
*      http://cvs.sakaiproject.org/licenses/license_1_0.html
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**********************************************************************************/

import org.w3c.dom.Node;
public class Utils {
  /**
   * Search up the tree for a given node
   * @param currentNode Starting point for our search
   * @param tagName Node name to look up
   * @return matching Node (null if none)
   */
  public static Node getPreviousNodeByName(Node currentNode, String tagName) {
    Node node = currentNode.getParentNode();
    while ((node != null) && (!node.getNodeName().equals(tagName))) {
      node = node.getParentNode();
    }
    return node;
  }
}





Traverse a DOM tree in order to get information about the document.

   
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.PrintWriter;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
/**
 * A sample DOM counter. This sample program illustrates how to
 * traverse a DOM tree in order to get information about the document.
 * The output of this program shows the time and count of elements,
 * attributes, ignorable whitespaces, and characters appearing in
 * the document. Three times are shown: the parse time, the first
 * traversal of the document, and the second traversal of the tree.
 * <p>
 * This class is useful as a "poor-man"s" performance tester to
 * compare the speed and accuracy of various DOM parsers. However,
 * it is important to note that the first parse time of a parser
 * will include both VM class load time and parser initialization
 * that would not be present in subsequent parses with the same
 * file.
 * <p>
 * <strong>Note:</strong> The results produced by this program
 * should never be accepted as true performance measurements.
 *
 * @author Andy Clark, IBM
 *
 * @version $Id: Counter.java 447683 2006-09-19 02:36:31Z mrglavas $
 */
public class Counter {
    //
    // Constants
    //
    // feature ids
    /** Namespaces feature id (http://xml.org/sax/features/namespaces). */
    protected static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces";
    /** Validation feature id (http://xml.org/sax/features/validation). */
    protected static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";
    /** Schema validation feature id (http://apache.org/xml/features/validation/schema). */
    protected static final String SCHEMA_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/schema";
    /** Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). */
    protected static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking";
    
    /** Honour all schema locations feature id (http://apache.org/xml/features/honour-all-schemaLocations). */
    protected static final String HONOUR_ALL_SCHEMA_LOCATIONS_ID = "http://apache.org/xml/features/honour-all-schemaLocations";
    
    /** Validate schema annotations feature id (http://apache.org/xml/features/validate-annotations). */
    protected static final String VALIDATE_ANNOTATIONS_ID = "http://apache.org/xml/features/validate-annotations";
    
    /** Dynamic validation feature id (http://apache.org/xml/features/validation/dynamic). */
    protected static final String DYNAMIC_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/dynamic";
    
    /** XInclude feature id (http://apache.org/xml/features/xinclude). */
    protected static final String XINCLUDE_FEATURE_ID = "http://apache.org/xml/features/xinclude";
    
    /** XInclude fixup base URIs feature id (http://apache.org/xml/features/xinclude/fixup-base-uris). */
    protected static final String XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID = "http://apache.org/xml/features/xinclude/fixup-base-uris";
    
    /** XInclude fixup language feature id (http://apache.org/xml/features/xinclude/fixup-language). */
    protected static final String XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID = "http://apache.org/xml/features/xinclude/fixup-language";
    // default settings
    /** Default parser name (dom.wrappers.Xerces). */
    protected static final String DEFAULT_PARSER_NAME = "dom.wrappers.Xerces";
    /** Default repetition (1). */
    protected static final int DEFAULT_REPETITION = 1;
    /** Default namespaces support (true). */
    protected static final boolean DEFAULT_NAMESPACES = true;
    /** Default validation support (false). */
    protected static final boolean DEFAULT_VALIDATION = false;
    /** Default Schema validation support (false). */
    protected static final boolean DEFAULT_SCHEMA_VALIDATION = false;
    /** Default Schema full checking support (false). */
    protected static final boolean DEFAULT_SCHEMA_FULL_CHECKING = false;
    
    /** Default honour all schema locations (false). */
    protected static final boolean DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS = false;
    
    /** Default validate schema annotations (false). */
    protected static final boolean DEFAULT_VALIDATE_ANNOTATIONS = false;
    /** Default dynamic validation support (false). */
    protected static final boolean DEFAULT_DYNAMIC_VALIDATION = false;
    
    /** Default XInclude processing support (false). */
    protected static final boolean DEFAULT_XINCLUDE = false;
    
    /** Default XInclude fixup base URIs support (true). */
    protected static final boolean DEFAULT_XINCLUDE_FIXUP_BASE_URIS = true;
    
    /** Default XInclude fixup language support (true). */
    protected static final boolean DEFAULT_XINCLUDE_FIXUP_LANGUAGE = true;
    //
    // Data
    //
    /** Number of elements. */
    protected long fElements;
    /** Number of attributes. */
    protected long fAttributes;
    /** Number of characters. */
    protected long fCharacters;
    /** Number of ignorable whitespace characters. */
    protected long fIgnorableWhitespace;
    /** Document information. */
    protected ParserWrapper.DocumentInfo fDocumentInfo;
    //
    // Public methods
    //
    /** Sets the parser wrapper. */
    public void setDocumentInfo(ParserWrapper.DocumentInfo documentInfo) {
        fDocumentInfo = documentInfo;
    } // setDocumentInfo(ParserWrapper.DocumentInfo)
    /** Traverses the specified node, recursively. */
    public void count(Node node) {
        // is there anything to do?
        if (node == null) {
            return;
        }
        int type = node.getNodeType();
        switch (type) {
            case Node.DOCUMENT_NODE: {
                fElements = 0;
                fAttributes = 0;
                fCharacters = 0;
                fIgnorableWhitespace = 0;
                Document document = (Document)node;
                count(document.getDocumentElement());
                break;
            }
            case Node.ELEMENT_NODE: {
                fElements++;
                NamedNodeMap attrs = node.getAttributes();
                if (attrs != null) {
                    fAttributes += attrs.getLength();
                }
                // drop through to entity reference
            }
            case Node.ENTITY_REFERENCE_NODE: {
                Node child = node.getFirstChild();
                while (child != null) {
                    count(child);
                    child = child.getNextSibling();
                }
                break;
            }
            case Node.CDATA_SECTION_NODE: {
                fCharacters += ((Text)node).getLength();
                break;
            }
            case Node.TEXT_NODE: {
                if (fDocumentInfo != null) {
                    Text text = (Text)node;
                    int length = text.getLength();
                    if (fDocumentInfo.isIgnorableWhitespace(text)) {
                        fIgnorableWhitespace += length;
                    }
                    else {
                        fCharacters += length;
                    }
                }
                break;
            }
        }
    } // count(Node)
    /** Prints the results. */
    public void printResults(PrintWriter out, String uri,
                             long parse, long traverse1, long traverse2,
                             int repetition) {
        // filename.xml: 631/200/100 ms (4 elems, 0 attrs, 78 spaces, 0 chars)
        out.print(uri);
        out.print(": ");
        if (repetition == 1) {
            out.print(parse);
        }
        else {
            out.print(parse);
            out.print("/");
            out.print(repetition);
            out.print("=");
            out.print(parse/repetition);
        }
        out.print(";");
        out.print(traverse1);
        out.print(";");
        out.print(traverse2);
        out.print(" ms (");
        out.print(fElements);
        out.print(" elems, ");
        out.print(fAttributes);
        out.print(" attrs, ");
        out.print(fIgnorableWhitespace);
        out.print(" spaces, ");
        out.print(fCharacters);
        out.print(" chars)");
        out.println();
        out.flush();
    } // printResults(PrintWriter,String,long,long,long)
    //
    // MAIN
    //
    /** Main program entry point. */
    public static void main(String argv[]) {
        // is there anything to do?
        if (argv.length == 0) {
            printUsage();
            System.exit(1);
        }
        // variables
        Counter counter = new Counter();
        PrintWriter out = new PrintWriter(System.out);
        ParserWrapper parser = null;
        int repetition = DEFAULT_REPETITION;
        boolean namespaces = DEFAULT_NAMESPACES;
        boolean validation = DEFAULT_VALIDATION;
        boolean schemaValidation = DEFAULT_SCHEMA_VALIDATION;
        boolean schemaFullChecking = DEFAULT_SCHEMA_FULL_CHECKING;
        boolean honourAllSchemaLocations = DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS;
        boolean validateAnnotations = DEFAULT_VALIDATE_ANNOTATIONS;
        boolean dynamicValidation = DEFAULT_DYNAMIC_VALIDATION;
        boolean xincludeProcessing = DEFAULT_XINCLUDE;
        boolean xincludeFixupBaseURIs = DEFAULT_XINCLUDE_FIXUP_BASE_URIS;
        boolean xincludeFixupLanguage = DEFAULT_XINCLUDE_FIXUP_LANGUAGE;
        // process arguments
        for (int i = 0; i < argv.length; i++) {
            String arg = argv[i];
            if (arg.startsWith("-")) {
                String option = arg.substring(1);
                if (option.equals("p")) {
                    // get parser name
                    if (++i == argv.length) {
                        System.err.println("error: Missing argument to -p option.");
                    }
                    String parserName = argv[i];
                    // create parser
                    try {
                        parser = (ParserWrapper)Class.forName(parserName).newInstance();
                    }
                    catch (Exception e) {
                        parser = null;
                        System.err.println("error: Unable to instantiate parser ("+parserName+")");
                    }
                    continue;
                }
                if (option.equals("x")) {
                    if (++i == argv.length) {
                        System.err.println("error: Missing argument to -x option.");
                        continue;
                    }
                    String number = argv[i];
                    try {
                        int value = Integer.parseInt(number);
                        if (value < 1) {
                            System.err.println("error: Repetition must be at least 1.");
                            continue;
                        }
                        repetition = value;
                    }
                    catch (NumberFormatException e) {
                        System.err.println("error: invalid number ("+number+").");
                    }
                    continue;
                }
                if (option.equalsIgnoreCase("n")) {
                    namespaces = option.equals("n");
                    continue;
                }
                if (option.equalsIgnoreCase("v")) {
                    validation = option.equals("v");
                    continue;
                }
                if (option.equalsIgnoreCase("s")) {
                    schemaValidation = option.equals("s");
                    continue;
                }
                if (option.equalsIgnoreCase("f")) {
                    schemaFullChecking = option.equals("f");
                    continue;
                }
                if (option.equalsIgnoreCase("hs")) {
                    honourAllSchemaLocations = option.equals("hs");
                    continue;
                }
                if (option.equalsIgnoreCase("va")) {
                    validateAnnotations = option.equals("va");
                    continue;
                }
                if (option.equalsIgnoreCase("dv")) {
                    dynamicValidation = option.equals("dv");
                    continue;
                }
                if (option.equalsIgnoreCase("xi")) {
                    xincludeProcessing = option.equals("xi");
                    continue;
                }
                if (option.equalsIgnoreCase("xb")) {
                    xincludeFixupBaseURIs = option.equals("xb");
                    continue;
                }
                if (option.equalsIgnoreCase("xl")) {
                    xincludeFixupLanguage = option.equals("xl");
                    continue;
                }
                if (option.equals("h")) {
                    printUsage();
                    continue;
                }
            }
            // use default parser?
            if (parser == null) {
                // create parser
                try {
                    parser = (ParserWrapper)Class.forName(DEFAULT_PARSER_NAME).newInstance();
                }
                catch (Exception e) {
                    System.err.println("error: Unable to instantiate parser ("+DEFAULT_PARSER_NAME+")");
                    continue;
                }
            }
            // set parser features
            try {
                parser.setFeature(NAMESPACES_FEATURE_ID, namespaces);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+NAMESPACES_FEATURE_ID+")");
            }
            try {
                parser.setFeature(VALIDATION_FEATURE_ID, validation);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+VALIDATION_FEATURE_ID+")");
            }
            try {
                parser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, schemaValidation);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+SCHEMA_VALIDATION_FEATURE_ID+")");
            }
            try {
                parser.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, schemaFullChecking);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+SCHEMA_FULL_CHECKING_FEATURE_ID+")");
            }
            try {
                parser.setFeature(HONOUR_ALL_SCHEMA_LOCATIONS_ID, honourAllSchemaLocations);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+HONOUR_ALL_SCHEMA_LOCATIONS_ID+")");
            }
            try {
                parser.setFeature(VALIDATE_ANNOTATIONS_ID, validateAnnotations);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+VALIDATE_ANNOTATIONS_ID+")");
            }
            try {
                parser.setFeature(DYNAMIC_VALIDATION_FEATURE_ID, dynamicValidation);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+DYNAMIC_VALIDATION_FEATURE_ID+")");
            }
            try {
                parser.setFeature(XINCLUDE_FEATURE_ID, xincludeProcessing);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+XINCLUDE_FEATURE_ID+")");
            }
            try {
                parser.setFeature(XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID, xincludeFixupBaseURIs);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+XINCLUDE_FIXUP_BASE_URIS_FEATURE_ID+")");
            }
            try {
                parser.setFeature(XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID, xincludeFixupLanguage);
            }
            catch (SAXException e) {
                System.err.println("warning: Parser does not support feature ("+XINCLUDE_FIXUP_LANGUAGE_FEATURE_ID+")");
            }
            // parse file
            try {
                long beforeParse = System.currentTimeMillis();
                Document document = null;
                for (int j = 0; j < repetition; j++) {
                    document = parser.parse(arg);
                }
                long afterParse = System.currentTimeMillis();
                long parse = afterParse - beforeParse;
                ParserWrapper.DocumentInfo documentInfo = parser.getDocumentInfo();
                counter.setDocumentInfo(documentInfo);
                long beforeTraverse1 = System.currentTimeMillis();
                counter.count(document);
                long afterTraverse1 = System.currentTimeMillis();
                long traverse1 = afterTraverse1 - beforeTraverse1;
                long beforeTraverse2 = System.currentTimeMillis();
                counter.count(document);
                long afterTraverse2 = System.currentTimeMillis();
                long traverse2 = afterTraverse2 - beforeTraverse2;
                counter.printResults(out, arg, parse, traverse1, traverse2,
                                     repetition);
            }
            catch (SAXParseException e) {
                // ignore
            }
            catch (Exception e) {
                System.err.println("error: Parse error occurred - "+e.getMessage());
                Exception se = e;
                if (e instanceof SAXException) {
                    se = ((SAXException)e).getException();
                }
                if (se != null)
                  se.printStackTrace(System.err);
                else
                  e.printStackTrace(System.err);
            }
        }
    } // main(String[])
    //
    // Private static methods
    //
    /** Prints the usage. */
    private static void printUsage() {
        System.err.println("usage: java dom.Counter (options) uri ...");
        System.err.println();
        System.err.println("options:");
        System.err.println("  -p name     Select parser by name.");
        System.err.println("  -x number   Select number of repetitions.");
        System.err.println("  -n  | -N    Turn on/off namespace processing.");
        System.err.println("  -v  | -V    Turn on/off validation.");
        System.err.println("  -s  | -S    Turn on/off Schema validation support.");
        System.err.println("              NOTE: Not supported by all parsers.");
        System.err.println("  -f  | -F    Turn on/off Schema full checking.");
        System.err.println("              NOTE: Requires use of -s and not supported by all parsers.");
        System.err.println("  -hs | -HS   Turn on/off honouring of all schema locations.");
        System.err.println("              NOTE: Requires use of -s and not supported by all parsers.");
        System.err.println("  -va | -VA   Turn on/off validation of schema annotations.");
        System.err.println("              NOTE: Requires use of -s and not supported by all parsers.");
        System.err.println("  -dv | -DV   Turn on/off dynamic validation.");
        System.err.println("              NOTE: Not supported by all parsers.");
        System.err.println("  -xi | -XI   Turn on/off XInclude processing.");
        System.err.println("              NOTE: Not supported by all parsers.");
        System.err.println("  -xb | -XB   Turn on/off base URI fixup during XInclude processing.");
        System.err.println("              NOTE: Requires use of -xi and not supported by all parsers.");
        System.err.println("  -xl | -XL   Turn on/off language fixup during XInclude processing.");
        System.err.println("              NOTE: Requires use of -xi and not supported by all parsers.");
        System.err.println("  -h          This help screen.");
        System.err.println();
        System.err.println("defaults:");
        System.err.println("  Parser:     "+DEFAULT_PARSER_NAME);
        System.err.println("  Repetition: "+DEFAULT_REPETITION);
        System.err.print("  Namespaces: ");
        System.err.println(DEFAULT_NAMESPACES ? "on" : "off");
        System.err.print("  Validation: ");
        System.err.println(DEFAULT_VALIDATION ? "on" : "off");
        System.err.print("  Schema:     ");
        System.err.println(DEFAULT_SCHEMA_VALIDATION ? "on" : "off");
        System.err.print("  Schema full checking:            ");
        System.err.println(DEFAULT_SCHEMA_FULL_CHECKING ? "on" : "off");
        System.err.print("  Honour all schema locations:     ");
        System.err.println(DEFAULT_HONOUR_ALL_SCHEMA_LOCATIONS ? "on" : "off");
        System.err.print("  Validate annotations:            ");
        System.err.println(DEFAULT_VALIDATE_ANNOTATIONS ? "on" : "off");
        System.err.print("  Dynamic:    ");
        System.err.println(DEFAULT_DYNAMIC_VALIDATION ? "on" : "off");
        System.err.print("  XInclude:   ");
        System.err.println(DEFAULT_XINCLUDE ? "on" : "off");
        System.err.print("  XInclude base URI fixup:  ");
        System.err.println(DEFAULT_XINCLUDE_FIXUP_BASE_URIS ? "on" : "off");
        System.err.print("  XInclude language fixup:  ");
        System.err.println(DEFAULT_XINCLUDE_FIXUP_LANGUAGE ? "on" : "off");
    } // printUsage()
} // class DOMCount

/**
 * Encapsulates a DOM parser.
 *
 * @version $Id: ParserWrapper.java 447683 2006-09-19 02:36:31Z mrglavas $
 */
 interface ParserWrapper {
    //
    // ParserWrapper methods
    //
    /** Parses the specified URI and returns the document. */
    public Document parse(String uri) throws Exception;
    /**
     * Set the state of a feature.
     *
     * Set the state of any feature in a SAX2 parser.  The parser
     * might not recognize the feature, and if it does recognize
     * it, it might not be able to fulfill the request.
     *
     * @param featureId The unique identifier (URI) of the feature.
     * @param state The requested state of the feature (true or false).
     *
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested feature is not known.
     * @exception org.xml.sax.SAXNotSupportedException If the
     *            requested feature is known, but the requested
     *            state is not supported.
     * @exception org.xml.sax.SAXException If there is any other
     *            problem fulfilling the request.
     */
    public void setFeature(String featureId, boolean state)
        throws  SAXNotRecognizedException, SAXNotSupportedException; 
    /** Returns the document information. */
    public DocumentInfo getDocumentInfo();
    //
    // Interfaces
    //
    /**
     * This interface is here to query information about the document
     * implementation returned by the <code>ParserWrapper#parse</code>
     * method.
     *
     * @author Andy Clark, IBM
     */
    public interface DocumentInfo {
        //
        // DocumentInfo methods
        //
        /** 
         * Returns true if the specified text node is ignorable whitespace. 
         */
        public boolean isIgnorableWhitespace(Text text);
    } // interface DocumentInfo
} // interface ParserWrapper





Traverse a DOM tree in order to print a document that is parsed.

 

/*
 * 
 *
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution, if
 *    any, must include the following acknowlegement:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 *
 * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
 *    Foundation" must not be used to endorse or promote products derived
 *    from this software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache"
 *    nor may "Apache" appear in their names without prior written
 *    permission of the Apache Group.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS"" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * Traverse a DOM tree in order to print a document that is parsed.
 *
 * @author Andy Clark, IBM
 * @author Thomas.Diesler@jboss.org
 */
@SuppressWarnings("unchecked")
public class DOMWriter
{
  // Print writer
  private PrintWriter out;
  // True, if canonical output
  private boolean canonical;
  // True, if pretty printing should be used
  private boolean prettyprint;
  // True, if the XML declaration should be written
  private boolean writeXMLDeclaration;
  // True, if whitespace should be ignored
  private boolean ignoreWhitespace;
  // Explicit character set encoding
  private String charsetName;
  // indent for the pretty printer
  private int prettyIndent;
  // True, if the XML declaration has been written
  private boolean wroteXMLDeclaration;
  // The node that started the write
  private Node rootNode;
  // True if we want namespace completion
  private boolean completeNamespaces = true;
  // The current default namespace
  private String currentDefaultNamespace;
  public DOMWriter(Writer w)
  {
    this.out = new PrintWriter(w);
  }
  public DOMWriter(Writer w, String charsetName)
  {
    this.out = new PrintWriter(w);
    this.charsetName = charsetName;
    this.writeXMLDeclaration = true;
  }
  public DOMWriter(OutputStream stream)
  {
    try
    {
      this.out = new PrintWriter(new OutputStreamWriter(stream, "UTF-8"));
    }
    catch (UnsupportedEncodingException e)
    {
      // ignore, UTF-8 should be available
    }
  }
  public DOMWriter(OutputStream stream, String charsetName)
  {
    try
    {
      this.out = new PrintWriter(new OutputStreamWriter(stream, charsetName));
      this.charsetName = charsetName;
      this.writeXMLDeclaration = true;
    }
    catch (UnsupportedEncodingException e)
    {
      throw new IllegalArgumentException("Unsupported encoding: " + charsetName);
    }
  }
  /**
   * Print a node with explicit prettyprinting.
   * The defaults for all other DOMWriter properties apply.
   *
   */
  public static String printNode(Node node, boolean prettyprint)
  {
    StringWriter strw = new StringWriter();
    new DOMWriter(strw).setPrettyprint(prettyprint).print(node);
    return strw.toString();
  }
  public boolean isCanonical()
  {
    return canonical;
  }
  /**
   * Set wheter entities should appear in their canonical form.
   * The default is false.
   */
  public DOMWriter setCanonical(boolean canonical)
  {
    this.canonical = canonical;
    return this;
  }
  public boolean isIgnoreWhitespace()
  {
    return ignoreWhitespace;
  }
  /**
   * Set whether whitespace should be ignored.
   * The default is false.
   */
  public DOMWriter setIgnoreWhitespace(boolean ignoreWhitespace)
  {
    this.ignoreWhitespace = ignoreWhitespace;
    return this;
  }
  /**
   * Set wheter subelements should have their namespaces completed.
   * Setting this to false may lead to invalid XML fragments.
   * The default is true.
   */
  public DOMWriter setCompleteNamespaces(boolean complete)
  {
    this.rupleteNamespaces = complete;
    return this;
  }
  public boolean isPrettyprint()
  {
    return prettyprint;
  }
  /**
   * Set wheter element should be indented.
   * The default is false.
   */
  public DOMWriter setPrettyprint(boolean prettyprint)
  {
    this.prettyprint = prettyprint;
    return this;
  }
  public boolean isWriteXMLDeclaration()
  {
    return writeXMLDeclaration;
  }
  /**
   * Set wheter the XML declaration should be written.
   * The default is false.
   */
  public DOMWriter setWriteXMLDeclaration(boolean flag)
  {
    this.writeXMLDeclaration = flag;
    return this;
  }
  public void print(Node node)
  {
    if (prettyprint && ignoreWhitespace)
      throw new IllegalStateException("Cannot pretty print and ignore whitespace");
    rootNode = node;
    printInternal(node, false);
  }
  private void printInternal(Node node, boolean indentEndMarker)
  {
    // is there anything to do?
    if (node == null)
    {
      return;
    }
    // JBAS-2117 - Don"t skip the DOCUMENT_NODE
    // if (node instanceof Document) node = ((Document)node).getDocumentElement();
    if (wroteXMLDeclaration == false && writeXMLDeclaration == true && canonical == false)
    {
      out.print("<?xml version="1.0"");
      if (charsetName != null)
        out.print(" encoding="" + charsetName + """);
      out.print("?>");
      if (prettyprint)
        out.println();
      wroteXMLDeclaration = true;
    }
    int type = node.getNodeType();
    boolean hasChildNodes = node.getChildNodes().getLength() > 0;
    String nodeName = node.getNodeName();
    switch (type)
    {
      // print document
      case Node.DOCUMENT_NODE:
      {
        NodeList children = node.getChildNodes();
        for (int iChild = 0; iChild < children.getLength(); iChild++)
        {
          printInternal(children.item(iChild), false);
        }
        out.flush();
        break;
      }
      // print element with attributes
      case Node.ELEMENT_NODE:
      {
        Element element = (Element)node;
        if (prettyprint)
        {
          for (int i = 0; i < prettyIndent; i++)
          {
            out.print(" ");
          }
          prettyIndent++;
        }
        out.print("<");
        out.print(nodeName);
        Map nsMap = new HashMap();
        String elPrefix = node.getPrefix();
        String elNamespaceURI = node.getNamespaceURI();
        if (elPrefix != null)
        {
          String nsURI = getNamespaceURI(elPrefix, element, rootNode);
          nsMap.put(elPrefix, nsURI);
        }
        Attr attrs[] = sortAttributes(node.getAttributes());
        for (int i = 0; i < attrs.length; i++)
        {
          Attr attr = attrs[i];
          String atPrefix = attr.getPrefix();
          String atName = attr.getNodeName();
          String atValue = normalize(attr.getNodeValue(), canonical);
          if (atName.equals("xmlns"))
            currentDefaultNamespace = atValue;
          if (atPrefix != null && !atPrefix.equals("xmlns") && !atPrefix.equals("xml"))
          {
            String nsURI = getNamespaceURI(atPrefix, element, rootNode);
            nsMap.put(atPrefix, nsURI);
            // xsi:type="ns1:SubType", xsi:type="xsd:string"
            if (atName.equals(atPrefix + ":type") && atValue.indexOf(":") > 0)
            {
              // xsi defined on the envelope
              if (nsURI == null)
                nsURI = getNamespaceURI(atPrefix, element, null);
              if ("http://www.w3.org/2001/XMLSchema-instance".equals(nsURI))
              {
                String typePrefix = atValue.substring(0, atValue.indexOf(":"));
                String typeURI = getNamespaceURI(typePrefix, element, rootNode);
                nsMap.put(typePrefix, typeURI);
              }
            }
          }
          out.print(" " + atName + "="" + atValue + """);
        }
        // Add namespace declaration for prefixes
        // that are defined further up the tree
        if (completeNamespaces)
        {
          Iterator itPrefix = nsMap.keySet().iterator();
          while (itPrefix.hasNext())
          {
            String prefix = (String)itPrefix.next();
            String nsURI = (String)nsMap.get(prefix);
            if (nsURI == null)
            {
              nsURI = getNamespaceURI(prefix, element, null);
              out.print(" xmlns:" + prefix + "="" + nsURI + """);
            }
          }
        }
        // The SAX ContentHandler will by default not add the namespace declaration
        // <Hello xmlns="http://somens">World</Hello>
        if (elPrefix == null && elNamespaceURI != null)
        {
          String defaultNamespace = element.getAttribute("xmlns");
          if (defaultNamespace.length() == 0 && !elNamespaceURI.equals(currentDefaultNamespace))
          {
            out.print(" xmlns="" + elNamespaceURI + """);
            currentDefaultNamespace = elNamespaceURI;
          }
        }
        if (hasChildNodes)
        {
          out.print(">");
        }
        // Find out if the end marker is indented
        indentEndMarker = isEndMarkerIndented(node);
        if (indentEndMarker)
        {
          out.print("\n");
        }
        NodeList childNodes = node.getChildNodes();
        int len = childNodes.getLength();
        for (int i = 0; i < len; i++)
        {
          Node childNode = childNodes.item(i);
          printInternal(childNode, false);
        }
        break;
      }
      // handle entity reference nodes
      case Node.ENTITY_REFERENCE_NODE:
      {
        if (canonical)
        {
          NodeList children = node.getChildNodes();
          if (children != null)
          {
            int len = children.getLength();
            for (int i = 0; i < len; i++)
            {
              printInternal(children.item(i), false);
            }
          }
        }
        else
        {
          out.print("&");
          out.print(nodeName);
          out.print(";");
        }
        break;
      }
      // print cdata sections
      case Node.CDATA_SECTION_NODE:
      {
        if (canonical)
        {
          out.print(normalize(node.getNodeValue(), canonical));
        }
        else
        {
          out.print("<![CDATA[");
          out.print(node.getNodeValue());
          out.print("]]&gt;");
        }
        break;
      }
      // print text
      case Node.TEXT_NODE:
      {
        String text = normalize(node.getNodeValue(), canonical);
        if (text.trim().length() > 0)
        {
          out.print(text);
        }
        else if (prettyprint == false && ignoreWhitespace == false)
        {
          out.print(text);
        }
        break;
      }
      // print processing instruction
      case Node.PROCESSING_INSTRUCTION_NODE:
      {
        out.print("<?");
        out.print(nodeName);
        String data = node.getNodeValue();
        if (data != null && data.length() > 0)
        {
          out.print(" ");
          out.print(data);
        }
        out.print("?>");
        break;
      }
      // print comment
      case Node.ruMENT_NODE:
      {
        for (int i = 0; i < prettyIndent; i++)
        {
          out.print(" ");
        }
        out.print("<!--");
        String data = node.getNodeValue();
        if (data != null)
        {
          out.print(data);
        }
        out.print("-->");
        if (prettyprint)
        {
          out.print("\n");
        }
        break;
      }
    }
    if (type == Node.ELEMENT_NODE)
    {
      if (prettyprint)
        prettyIndent--;
      if (hasChildNodes == false)
      {
        out.print("/>");
      }
      else
      {
        if (indentEndMarker)
        {
          for (int i = 0; i < prettyIndent; i++)
          {
            out.print(" ");
          }
        }
        out.print("</");
        out.print(nodeName);
        out.print(">");
      }
      if (prettyIndent > 0)
      {
        out.print("\n");
      }
    }
    out.flush();
  }
  private String getNamespaceURI(String prefix, Element element, Node stopNode)
  {
    Node parent = element.getParentNode();
    String nsURI = element.getAttribute("xmlns:" + prefix);
    if (nsURI.length() == 0 && element != stopNode && parent instanceof Element)
      return getNamespaceURI(prefix, (Element)parent, stopNode);
    return (nsURI.length() > 0 ? nsURI : null);
  }
  private boolean isEndMarkerIndented(Node node)
  {
    if (prettyprint)
    {
      NodeList childNodes = node.getChildNodes();
      int len = childNodes.getLength();
      for (int i = 0; i < len; i++)
      {
        Node children = childNodes.item(i);
        if (children.getNodeType() == Node.ELEMENT_NODE)
        {
          return true;
        }
      }
    }
    return false;
  }
  /** Returns a sorted list of attributes. */
  private Attr[] sortAttributes(NamedNodeMap attrs)
  {
    int len = (attrs != null) ? attrs.getLength() : 0;
    Attr array[] = new Attr[len];
    for (int i = 0; i < len; i++)
    {
      array[i] = (Attr)attrs.item(i);
    }
    for (int i = 0; i < len - 1; i++)
    {
      String name = array[i].getNodeName();
      int index = i;
      for (int j = i + 1; j < len; j++)
      {
        String curName = array[j].getNodeName();
        if (curName.rupareTo(name) < 0)
        {
          name = curName;
          index = j;
        }
      }
      if (index != i)
      {
        Attr temp = array[i];
        array[i] = array[index];
        array[index] = temp;
      }
    }
    return (array);
  }
  /** Normalizes the given string. */
  public static String normalize(String s, boolean canonical)
  {
    StringBuffer str = new StringBuffer();
    int len = (s != null) ? s.length() : 0;
    for (int i = 0; i < len; i++)
    {
      char ch = s.charAt(i);
      switch (ch)
      {
        case "<":
        {
          str.append("&lt;");
          break;
        }
        case ">":
        {
          str.append("&gt;");
          break;
        }
        case "&":
        {
          str.append("&amp;");
          break;
        }
        case """:
        {
          str.append("&quot;");
          break;
        }
        case "\"":
        {
          str.append("&apos;");
          break;
        }
        case "\r":
        case "\n":
        {
          if (canonical)
          {
            str.append("&#");
            str.append(Integer.toString(ch));
            str.append(";");
            break;
          }
          // else, default append char
        }
        default:
        {
          str.append(ch);
        }
      }
    }
    return (str.toString());
  }
}





Traverse the DOM tree as a list

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.NodeIterator;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.parse("sample.xml");
    DocumentTraversal traversal = (DocumentTraversal) document;
    NodeIterator iterator = traversal.createNodeIterator(document.getDocumentElement(),
        NodeFilter.SHOW_ELEMENT, null, true);
    for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) {
      System.out.println("Element: " + ((Element) n).getTagName());
    }
  }
}





Traverse the DOM tree using TreeWalker

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.TreeWalker;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.parse("sample.xml");
    DocumentTraversal traversal = (DocumentTraversal) document;
    TreeWalker walker = traversal.createTreeWalker(document.getDocumentElement(),
        NodeFilter.SHOW_ELEMENT, null, true);
    traverseLevel(walker, "");
  }
  private static final void traverseLevel(TreeWalker walker, String indent) {
    Node parend = walker.getCurrentNode();
    System.out.println(indent + "- " + ((Element) parend).getTagName());
    for (Node n = walker.firstChild(); n != null; n = walker.nextSibling()) {
      traverseLevel(walker, indent + "\t");
    }
    walker.setCurrentNode(parend);
  }
}





Using ranges in DOM tree

     
 
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.ranges.DocumentRange;
import org.w3c.dom.ranges.Range;
public class Main {
  public static void main(String[] argv) throws Exception {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder loader = factory.newDocumentBuilder();
    Document document = loader.parse("sample.xml");
    Element order = document.getDocumentElement();
    DocumentRange ranges = (DocumentRange) document;
    Range range = ranges.createRange();
    range.setStartBefore(order.getFirstChild());
    range.setEndAfter(order.getLastChild());
    range.deleteContents();
    range.detach();
  }
}