To exemplify the easy usage of XML, we will show you how to develop a basic
XML file viewer. This is done
1. by using the SpeedJG XML classes, and
2. by means of an XMLTreeModel implementation based on the W3C DOM.
The GUI of this application consists of a JSplitPane with a JTree to navigate on the left and a JTextArea to show the contents on the right. In addition, there is a JPopupMenu available on the text area to copy the contents into the system clipboard.
To generate the source code, open the project ${YourPathToSpeedJG}/Examples.gpr. Select the JFrame xmlTreeView and follow these steps to get a first outline of the Java source code:
To customize the source code according to our needs in order to show the expected results we only have to make changes within the
XmlTreeView.java file and there only within the model class XmlTreeView.
The generated view code (XmlTreeViewGUI
) and controller code (XmlTreeViewController
)
remain unchanged. Thus, if you modify the layout of your GUI with SpeedJG and re-generate the code, your individually added code lines
handling the GUI access remain untouched and valid because SpeedJG by default only overwrites the previously generated view and
controller code.
First, add the following import statements at the beginning of the XmlTreeView.java file because we need these for some methods we will call later on.
import speed.util.*; import java.awt.event.*; import java.awt.datatransfer.*; import javax.swing.event.*; import java.io.*;
Next, replace the generated declaration and instantiation code lines of the model class XmlTreeView from:
public class XmlTreeView { public XmlTreeView() { GUIObject gui = new XmlTreeViewGUI(); //XmlTreeViewController controller = new XmlTreeViewController(gui); JFrame frame = (JFrame) gui.getComponent("xmlTreeView"); frame.show(); } ...
to:
public class XmlTreeView extends XmlTreeViewController { public XmlTreeView() { super(new XmlTreeViewGUI()); xmlTreeView.show(); } ...
For performance and resource reasons SpeedJG implements its own lean XML DOM and also a JTree model that handles a XML document in a JTree-specific manner. Thus you are able not only to handle XML documents within a JTree but also to substitute the default JTree model with an XML-based model!
In our example the instantiation of the SpeedJG XMLDocumentTree is done when opening an XML file.
private XMLDocumentTree openXMLDocument() throws Exception { File file = getXMLFile(); if (file == null) return null; return new XMLDocumentTree(XMLDocument.fromFile(file.getPath()).getContent()); } private class XMLFileFilter extends javax.swing.filechooser.FileFilter { public boolean accept(File file) { return file.getName().toLowerCase().endsWith(".gpr") || file.getName().toLowerCase().endsWith(".xml") || file.isDirectory(); } public String getDescription() { return "SpeedJG Files, XML Files ( *.gpr, *.xml )"; } } private File getXMLFile() { JFileChooser jfc = new JFileChooser(); jfc.setCurrentDirectory(new File(".")); jfc.setFileFilter(new XMLFileFilter()); jfc.removeChoosableFileFilter(jfc.getAcceptAllFileFilter()); int result = jfc.showOpenDialog(null); if (result != JFileChooser.APPROVE_OPTION) { return null; } else { return jfc.getSelectedFile(); } }
At last, to make our example run, we have to overwrite some methods inherited from the controller class XmlTreeViewController.
void initialize() { selectionTree.setModel(null); }
void handleOpenMenuItemActionPerformedEvent(ActionEvent e) throws Exception { selectionTree.setModel(openXMLDocument()); xmlTextArea.setText(null); }
void handleSelectionTreeValueChangedEvent(TreeSelectionEvent e) throws Exception { Object[] path = e.getPath().getPath(); XMLElement nodeElement = (XMLElement)path[path.length - 1]; xmlTextArea.setText(nodeElement.asXMLString()); xmlTextArea.setCaretPosition(0); }
void handleCopyMenuItemActionPerformedEvent(ActionEvent e) throws Exception { Clipboard clipBoard = Toolkit.getDefaultToolkit().getSystemClipboard(); clipBoard.setContents(new StringSelection(xmlTextArea.getText()), null); }
void handleExitMenuItemActionPerformedEvent(ActionEvent e) throws Exception { System.exit(0); }
If you want to test and experiment with this example you have to obtain the following files:
XML Tree View Application Files | |
---|---|
SpeedJG.jar |
Contains the classes GUIObject and XMLDocumentTree. Download and un-zip the SpeedJG.zip file and place the SpeedJG.jar file on your CLASSPATH. |
XmlTreeView.java | Generated by SpeedJG and modified within this example. |
XmlTreeViewController.java | Generated by SpeedJG. |
If you prefer a tree model that works together with all current implementations of the W3C DOM, or if you want to build an application without the need to include classes from the SpeedJG.jar, you can also use the XmlTreeModel we have provided for these purposes, and that works similar to the SpeedJG XMLDocumentTree. I will not go into detail here because this would be a chapter of its own. So you can study this class and look into the respective literature for particular explanations. But already here I want to mention, that the XmlTreeModel.class references a XmlTreeNodeFilter interface that will not be explained until the next example - XML Tree Edit - because it is not used within this example.
To adapt our example above, we first have to modify the import statements at the beginning of the XmlTreeView.java file, and make the following changes:
from | to |
---|---|
... import speed.jg.*; import speed.util.*; ... |
... import javax.xml.parsers.*; import org.w3c.dom.*; ... |
Also comment out the following import statement at the beginning of the XmlTreeViewController.java file:
... //import speed.jg.*; ...
Next we have to change the openXMLDocument()
method that provides a new tree model for us:
private XmlTreeModel openXMLDocument() throws Exception { File file = getXMLFile(); if (file == null) return null; DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); XmlTreeModel xmlTreeModel = new XmlTreeModel(documentBuilder.parse(file).getDocumentElement()); return xmlTreeModel; }
At last we have to modify the method handling the tree selection events because these events now deliver Nodes as defined within the W3C DOM interfaces:
void handleSelectionTreeValueChangedEvent(TreeSelectionEvent e) throws Exception { Object[] path = e.getPath().getPath(); Node nodeElement = (Node)path[path.length - 1]; xmlTextArea.setText(nodeElement.toString()); xmlTextArea.setCaretPosition(0); }
If you want to test and experiment with this example you have to store the following files into a directory of your choice and subsequently compile them:
W3C DOM XML Tree View Application Files | |
---|---|
GUIObject.java | Superclass of all view classes generated by SpeedJG. |
XmlTreeView.java | Generated by SpeedJG and modified within this example. |
XmlTreeViewController.java | Generated by SpeedJG. |
XmlTreeModel.java | TreeModel for XML Documents that are implemented according to the W3C DOM standard. |
XmlTreeNodeFilter.java | Interface to be implemented by classes that interact with the XmlTreeModel. |
If you execute this example you will see some differences to the example based on the SpeedJG XML classes. This is because:
If you want to customize the representation of an XML document within a JTree, look at the next example - XML Tree Edit - where the XmlTreeNodeFilter comes into play.
Copyright © 2003 Wöhrmann Softwareentwicklung - Munich Germany