Java/XML/DOM Tree
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Accessing different types of DOM tree nodes
- 2 Copying a Subtree of Nodes from One DOM Document to Another
- 3 Copying a Subtree of Nodes in a DOM Document
- 4 Create new DOM tree with fully qualified element names
- 5 Creating a new DOM tree
- 6 DOM Util: get Child Text
- 7 Get Child Content
- 8 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.
- 9 Gets the child of the specified element having the specified unique name
- 10 Get the first child of the specified type.
- 11 Get the first child"s content ( ie it"s included TEXT node ).
- 12 Get the first direct child with a given type
- 13 Get this Document"s root node
- 14 Manipulate w3c DOM trees
- 15 Print Tree node
- 16 Reading a DOM tree from XML document
- 17 Returns an iterator over the children of the given element with the given tag name
- 18 Returns the concatenated child text of the specified node.
- 19 Return the next sibling with a given name and type
- 20 Saving a DOM tree to XML file javax.xml.parsers (JAXP)
- 21 Search earlier siblings for a given node
- 22 Search for a named child of a given node
- 23 Search our next siblings for a given node
- 24 Search up the tree for a given node
- 25 Traverse a DOM tree in order to get information about the document.
- 26 Traverse a DOM tree in order to print a document that is parsed.
- 27 Traverse the DOM tree as a list
- 28 Traverse the DOM tree using TreeWalker
- 29 Using ranges in DOM tree
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("]]>");
}
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("<");
break;
}
case ">":
{
str.append(">");
break;
}
case "&":
{
str.append("&");
break;
}
case """:
{
str.append(""");
break;
}
case "\"":
{
str.append("'");
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();
}
}