//XMLTree.java
//Uses the following files
Uses the following files:
* XMLFrame.java:Swing application to select an XML document and display in a JTree.
ExtensionFileFilter.java Allows you to specify which file extensions will be displayed in a JFileChooser.
test.xml Default file loaded if none selected by user.
perennials.xml and perennials.dtd Data on daylilies and corresponding DTD.
WindowUtilities.java
ExitListener.java.
//XMLTree.java as follows
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.io.*;
import org.w3c.dom.*;
import javax.xml.parsers.*;
/** Given a filename or a name and an input stream,
* this class generates a JTree representing the
* XML structure contained in the file or stream.
* Parses with DOM then copies the tree structure
* (minus text and comment nodes).
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
*
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class XMLTree extends JTree {
public XMLTree(String filename) throws IOException {
this(filename, new FileInputStream(new File(filename)));
}
public XMLTree(String filename, InputStream in) {
super(makeRootNode(in));
}
// This method needs to be static so that it can be called
// from the call to the parent constructor (super), which
// occurs before the object is really built.
private static DefaultMutableTreeNode
makeRootNode(InputStream in) {
try {
// Use JAXP's DocumentBuilderFactory so that there
// is no code here that is dependent on a particular
// DOM parser. Use the system property
// javax.xml.parsers.DocumentBuilderFactory (set either
// from Java code or by using the -D option to "java").
// or jre_dir/lib/jaxp.properties to specify this.
DocumentBuilderFactory builderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder builder =
builderFactory.newDocumentBuilder();
// Standard DOM code from hereon. The "parse"
// method invokes the parser and returns a fully parsed
// Document object. We'll then recursively descend the
// tree and copy non-text nodes into JTree nodes.
Document document = builder.parse(in);
document.getDocumentElement().normalize();
Element rootElement = document.getDocumentElement();
DefaultMutableTreeNode rootTreeNode =
buildTree(rootElement);
return(rootTreeNode);
} catch(Exception e) {
String errorMessage =
"Error making root node: " + e;
System.err.println(errorMessage);
e.printStackTrace();
return(new DefaultMutableTreeNode(errorMessage));
}
}
private static DefaultMutableTreeNode
buildTree(Element rootElement) {
// Make a JTree node for the root, then make JTree
// nodes for each child and add them to the root node.
// The addChildren method is recursive.
DefaultMutableTreeNode rootTreeNode =
new DefaultMutableTreeNode(treeNodeLabel(rootElement));
addChildren(rootTreeNode, rootElement);
return(rootTreeNode);
}
private static void addChildren
(DefaultMutableTreeNode parentTreeNode,
Node parentXMLElement) {
// Recursive method that finds all the child elements
// and adds them to the parent node. We have two types
// of nodes here: the ones corresponding to the actual
// XML structure and the entries of the graphical JTree.
// The convention is that nodes corresponding to the
// graphical JTree will have the word "tree" in the
// variable name. Thus, "childElement" is the child XML
// element whereas "childTreeNode" is the JTree element.
// This method just copies the non-text and non-comment
// nodes from the XML structure to the JTree structure.
NodeList childElements =
parentXMLElement.getChildNodes();
for(int i=0; i
// JTree Node: blah
// XML Element:
// JTree Node: blah (foo=bar, baz=quux)
private static String treeNodeLabel(Node childElement) {
NamedNodeMap elementAttributes =
childElement.getAttributes();
String treeNodeLabel = childElement.getNodeName();
if (elementAttributes != null &&
elementAttributes.getLength() > 0) {
treeNodeLabel = treeNodeLabel + " (";
int numAttributes = elementAttributes.getLength();
for(int i=0; i 0) {
treeNodeLabel = treeNodeLabel + ", ";
}
treeNodeLabel =
treeNodeLabel + attribute.getNodeName() +
"=" + attribute.getNodeValue();
}
treeNodeLabel = treeNodeLabel + ")";
}
return(treeNodeLabel);
}
}
XMLFrame.java Swing application to select an XML document and display in a JTree.
import java.awt.*;
import javax.swing.*;
import java.io.*;
/** Invokes an XML parser on an XML document and displays
* the document in a JTree. Both the parser and the
* document can be specified by the user. The parser
* is specified by invoking the program with
* java -Djavax.xml.parsers.DocumentBuilderFactory=xxx XMLFrame
* If no parser is specified, the Apache Xerces parser is used.
* The XML document can be supplied on the command
* line, but if it is not given, a JFileChooser is used
* to interactively select the file of interest.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class XMLFrame extends JFrame {
public static void main(String[] args) {
String jaxpPropertyName =
"javax.xml.parsers.DocumentBuilderFactory";
// Pass the parser factory in on the command line with
// -D to override the use of the Apache parser.
if (System.getProperty(jaxpPropertyName) == null) {
String apacheXercesPropertyValue =
"org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
System.setProperty(jaxpPropertyName,
apacheXercesPropertyValue);
}
String filename;
if (args.length > 0) {
filename = args[0];
} else {
String[] extensions = { "xml", "tld" };
WindowUtilities.setNativeLookAndFeel();
filename = ExtensionFileFilter.getFileName(".",
"XML Files",
extensions);
if (filename == null) {
filename = "test.xml";
}
}
new XMLFrame(filename);
}
public XMLFrame(String filename) {
try {
WindowUtilities.setNativeLookAndFeel();
JTree tree = new XMLTree(filename);
JFrame frame = new JFrame(filename);
frame.addWindowListener(new ExitListener());
Container content = frame.getContentPane();
content.add(new JScrollPane(tree));
frame.pack();
frame.setVisible(true);
} catch(IOException ioe) {
System.out.println("Error creating tree: " + ioe);
}
}
}
ExtensionFileFilter.java Allows you to specify which file extensions will be displayed in a JFileChooser.
import java.io.File;
import java.util.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
/** A FileFilter that lets you specify which file extensions
* will be displayed. Also includes a static getFileName
* method that users can call to pop up a JFileChooser for
* a set of file extensions.
*
* Adapted from Sun SwingSet demo.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class ExtensionFileFilter extends FileFilter {
public static final int LOAD = 0;
public static final int SAVE = 1;
private String description;
private boolean allowDirectories;
private Hashtable extensionsTable = new Hashtable();
private boolean allowAll = false;
public ExtensionFileFilter(boolean allowDirectories) {
this.allowDirectories = allowDirectories;
}
public ExtensionFileFilter() {
this(true);
}
public static String getFileName(String initialDirectory,
String description,
String extension) {
String[] extensions = new String[]{ extension };
return(getFileName(initialDirectory, description,
extensions, LOAD));
}
public static String getFileName(String initialDirectory,
String description,
String extension,
int mode) {
String[] extensions = new String[]{ extension };
return(getFileName(initialDirectory, description,
extensions, mode));
}
public static String getFileName(String initialDirectory,
String description,
String[] extensions) {
return(getFileName(initialDirectory, description,
extensions, LOAD));
}
/** Pops up a JFileChooser that lists files with the
* specified extensions. If the mode is SAVE, then the
* dialog will have a Save button; otherwise, the dialog
* will have an Open button. Returns a String corresponding
* to the file's pathname, or null if Cancel was selected.
*/
public static String getFileName(String initialDirectory,
String description,
String[] extensions,
int mode) {
ExtensionFileFilter filter = new ExtensionFileFilter();
filter.setDescription(description);
for(int i=0; i
WindowUtilities.java
import javax.swing.*;
import java.awt.*; // For Color and Container classes.
/** A few utilities that simplify using windows in Swing.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
*
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class WindowUtilities {
/** Tell system to use native look and feel, as in previous
* releases. Metal (Java) LAF is the default otherwise.
*/
public static void setNativeLookAndFeel() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
System.out.println("Error setting native LAF: " + e);
}
}
public static void setJavaLookAndFeel() {
try {
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
} catch(Exception e) {
System.out.println("Error setting Java LAF: " + e);
}
}
public static void setMotifLookAndFeel() {
try {
UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.motif.MotifLookAndFeel");
} catch(Exception e) {
System.out.println("Error setting Motif LAF: " + e);
}
}
/** A simplified way to see a JPanel or other Container. Pops
* up a JFrame with specified Container as the content pane.
*/
public static JFrame openInJFrame(Container content,
int width,
int height,
String title,
Color bgColor) {
JFrame frame = new JFrame(title);
frame.setBackground(bgColor);
content.setBackground(bgColor);
frame.setSize(width, height);
frame.setContentPane(content);
frame.addWindowListener(new ExitListener());
frame.setVisible(true);
return(frame);
}
/** Uses Color.white as the background color. */
public static JFrame openInJFrame(Container content,
int width,
int height,
String title) {
return(openInJFrame(content, width, height,
title, Color.white));
}
/** Uses Color.white as the background color, and the
* name of the Container's class as the JFrame title.
*/
public static JFrame openInJFrame(Container content,
int width,
int height) {
return(openInJFrame(content, width, height,
content.getClass().getName(),
Color.white));
}
}
EXITListener.java
import java.awt.*;
import java.awt.event.*;
/** A listener that you attach to the top-level JFrame of
* your application, so that quitting the frame exits the
* application.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
*
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
public class ExitListener extends WindowAdapter {
public void windowClosing(WindowEvent event) {
System.exit(0);
}
}