/*
* Copyright (c) 2000 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.com/javaexamples2.
*/
package com.davidflanagan.examples.xml;
import org.w3c.dom.*; // Core DOM classes
import org.w3c.dom.traversal.*; // TreeWalker and related DOM classes
import org.apache.xerces.parsers.*; // Apache Xerces parser classes
import org.xml.sax.*; // Xerces DOM parser uses some SAX classes
import javax.swing.*; // Swing classes
import javax.swing.tree.*; // TreeModel and related classes
import javax.swing.event.*; // Tree-related event classes
import java.io.*; // For reading the input XML file
/**
* This class implements the Swing TreeModel interface so that the DOM tree
* returned by a TreeWalker can be displayed in a JTree component.
**/
public class DOMTreeWalkerTreeModel implements TreeModel {
TreeWalker walker; // The TreeWalker we're modeling for JTree
/** Create a TreeModel for the specified TreeWalker */
public DOMTreeWalkerTreeModel(TreeWalker walker) { this.walker = walker; }
/**
* Create a TreeModel for a TreeWalker that returns all nodes
* in the specified document
**/
public DOMTreeWalkerTreeModel(Document document) {
DocumentTraversal dt = (DocumentTraversal)document;
walker = dt.createTreeWalker(document, NodeFilter.SHOW_ALL,null,false);
}
/**
* Create a TreeModel for a TreeWalker that returns the specified
* element and all of its descendant nodes.
**/
public DOMTreeWalkerTreeModel(Element element) {
DocumentTraversal dt = (DocumentTraversal)element.getOwnerDocument();
walker = dt.createTreeWalker(element, NodeFilter.SHOW_ALL, null,false);
}
// Return the root of the tree
public Object getRoot() { return walker.getRoot(); }
// Is this node a leaf? (Leaf nodes are displayed differently by JTree)
public boolean isLeaf(Object node) {
walker.setCurrentNode((Node)node); // Set current node
Node child = walker.firstChild(); // Ask for a child
return (child == null); // Does it have any?
}
// How many children does this node have?
public int getChildCount(Object node) {
walker.setCurrentNode((Node)node); // Set the current node
// TreeWalker doesn't count children for us, so we count ourselves
int numkids = 0;
Node child = walker.firstChild(); // Start with the first child
while(child != null) { // Loop 'till there are no more
numkids++; // Update the count
child = walker.nextSibling(); // Get next child
}
return numkids; // This is the number of children
}
// Return the specified child of a parent node.
public Object getChild(Object parent, int index) {
walker.setCurrentNode((Node)parent); // Set the current node
// TreeWalker provides sequential access to children, not random
// access, so we've got to loop through the kids one by one
Node child = walker.firstChild();
while(index-- > 0) child = walker.nextSibling();
return child;
}
// Return the index of the child node in the parent node
public int getIndexOfChild(Object parent, Object child) {
walker.setCurrentNode((Node)parent); // Set current node
int index = 0;
Node c = walker.firstChild(); // Start with first child
while((c != child) && (c != null)) { // Loop 'till we find a match
index++;
c = walker.nextSibling(); // Get the next child
}
return index; // Return matching position
}
// Only required for editable trees; unimplemented here.
public void valueForPathChanged(TreePath path, Object newvalue) {}
// This TreeModel never fires any events (since it is not editable)
// so event listener registration methods are left unimplemented
public void addTreeModelListener(TreeModelListener l) {}
public void removeTreeModelListener(TreeModelListener l) {}
/**
* This main() method demonstrates the use of this class, the use of the
* Xerces DOM parser, and the creation of a DOM Level 2 TreeWalker object.
**/
public static void main(String[] args) throws IOException, SAXException {
// Obtain an instance of a Xerces parser to build a DOM tree.
// Note that we are not using the JAXP API here, so this
// code uses Apache Xerces APIs that are not standards
DOMParser parser = new org.apache.xerces.parsers.DOMParser();
// Get a java.io.Reader for the input XML file and
// wrap the input file in a SAX input source
Reader in = new BufferedReader(new FileReader(args[0]));
InputSource input = new org.xml.sax.InputSource(in);
// Tell the Xerces parser to parse the input source
parser.parse(input);
// Ask the parser to give us our DOM Document. Once we've got the DOM
// tree, we don't have to use the Apache Xerces APIs any more; from
// here on, we use the standard DOM APIs
Document document = parser.getDocument();
// If we're using a DOM Level 2 implementation, then our Document
// object ought to implement DocumentTraversal
DocumentTraversal traversal = (DocumentTraversal)document;
// For this demonstration, we create a NodeFilter that filters out
// Text nodes containing only space; these just clutter up the tree
NodeFilter filter = new NodeFilter() {
public short acceptNode(Node n) {
if (n.getNodeType() == Node.TEXT_NODE) {
// Use trim() to strip off leading and trailing space.
// If nothing is left, then reject the node
if (((Text)n).getData().trim().length() == 0)
return NodeFilter.FILTER_REJECT;
}
return NodeFilter.FILTER_ACCEPT;
}
};
// This set of flags says to "show" all node types except comments
int whatToShow = NodeFilter.SHOW_ALL & ~NodeFilter.SHOW_COMMENT;
// Create a TreeWalker using the filter and the flags
TreeWalker walker = traversal.createTreeWalker(document, whatToShow,
filter, false);
// Instantiate a TreeModel and a JTree to display it
JTree tree = new JTree(new DOMTreeWalkerTreeModel(walker));
// Create a frame and a scrollpane to display the tree, and pop them up
JFrame frame = new JFrame("DOMTreeWalkerTreeModel Demo");
frame.getContentPane().add(new JScrollPane(tree));
frame.setSize(500, 250);
frame.setVisible(true);
}
}
评论0