Editor’s note: This is the first of a three-part series about how to build your own XML editor.
f you’ve been looking for a cross-platform, open-source XML editor, you’ve likely come up short. In the following series of three articles, I will walk you through the development of a simple, no frills, XML editor, utilizing several of the most common Java 2 Swing components. This series will be beneficial to anyone wanting to write their own XML editor, or just to those of you looking to learn or brush up on Swing.
In this first article, we will briefly discuss XML and why a tree structure is appropriate to display XML, and then we will take a look at the JAXP API and how to set up your environment with the necessary XML classes. Then we will learn about the JTree Swing component that displays a graphical tree (a common component in many XML editors). Finally, we will build a reusable class that extends the JTree component that is capable of parsing an XML document and displaying its data in a JTree.
In the second article, we will create the framework for our XML editor. In order to do so, we will cover a variety of Swing components (including JSplitPanes, JScrollPanes, JButtons, and JTextAreas).
In the third and final article, we will add the finishing touches to our editor by building a JMenu component and adding it to the editor. Additionally, we will construct JFileChooser components to access the underlying file system to allow XML documents to be saved and new documents to be opened.
How can I create a visual representation of an XML document?
Create a custom class that extends JTree, capable of parsing an XML file into a DOM object and constructing a JTree from that object.
Handling XML Data
(Editor’s note: If you already know how to work with XML data and you have downloaded the latest version of the xerces.jar from the Apache Group, then you may move on to the next page.)
One of the most common misunderstandings about the eXtensible Markup Language (XML) is that it is a new way of displaying data in a Web browser, akin to HTML or Cascading Style Sheets (CSS). The truth is that XML is a data-representation language, not a data-presentation language. It allows you to describe your data in a meaningful way. XML enables you to declare that “these three words constitute a heading,” “this is the byline,” and “this section constitutes the article body.” XML allows you to declare what a particular piece of data is, rather than how that data should appear in a Web page.
Consider the following XML sample:
Notice that these elements are different from standard HTML, but they look similar to HTML. This is because both HTML and XML have the same origin, SGML. The difference is that HTML has a predefined tag set, and XML’s grammar is flexible, allowing you to surround data with a meaningful tag (like
The Java API for XML Processing (JAXP) enables applications to parse and transform XML documents using a pure Java API that is independent of a particular XML processor implementation. It functions similar to the JDBC API, in that the developer is abstracted from the details of the underlying vendor specific component (an XML parser in the case of JAXP). The Apache Group’s Xerces parser provides the most up-to-date support for the JAXP API. In order to run the code developed later in this article, you will need to download the 1.3.1 Xerces binaries for your system (2.0 is still in alpha stage) from this link. Once you have downloaded the archive, extract the xerces.jar file and place it somewhere in your classpath. You can also download the xerces.jar via a link at the end of this article.
Next, we’ll learn how to use the JTree Swing component.
Working with the JTree Component
In nature, a tree has a common trunk from which branches extend. From those branches more branches extend. Every branch is related to every other branch in some way because they all have a common source, the trunk. This hierarchical relationship is not unique to trees; human genealogies follow much the same pattern. From a common set of parents, extend one or more children, each of those children potentially have one or more children, and the pattern continues ad infinitum.
In terms of data storage, a tree is a way of storing data that is organized in a manner similar to a genealogical tree. Each branch of the tree is called a node. The common parent node to all child nodes is called the root node. Every node that has child nodes is called a parent node (even if it, in turn, is a child of another node). A JTree component is simply a visual representation of a tree data structure.
Figure 1 shows a screen shot of a JTree component.
Almost every XML editor includes a visual tree structure like this one that allows you to edit and navigate through the elements contained in the XML document. We will construct one of these in the next section, but first we need to learn a little more about the JTree component.
A node stores data at a particular position in the tree. In addition to containing data, it knows about its parent node and any child nodes for which it is a parent. The javax.swing.tree package defines a handful of interfaces that provide a common way of building and manipulating a tree structure.
- TreeNode?declares methods used to access information about a tree node
- MutableTreeNode?declares methods used on a mutable tree (one that can add and remove child nodes)
- TreeModel?declares methods used to create and manage the data model associated with a tree.
Next, we’ll create a class that extends JTree and provides methods that allow an XML document to be parsed and displayed as visual nodes in a JTree component.
Creating the XTree Component
The XTree class consists of one constructor and three methods. Our simple implementation of the XTree component merely builds an Xtree; it does not provide for any manipulation of tree nodes after the tree has initially been built. As such, every method within the XTree class is called from the constructor.
Here’s a look at XTree API:
- private DefaultMutableTreeNode treeNode?This member stores the TreeNode object used to create the model for the JTree. The DefaultMutableTreeNode class is defined in the javax.swing.tree package and provides a default implementation of the MutableTreeNode interface.
- private DocumentBuilderFactory dbf
- private DocumentBuilder db
- private Document doc?These three members are a part of the JAXP API and are used to parse the XML text into a DOM object (of type Document).
- public XTree( String text )?This single constructor builds an XTree object using the XML text passed in through the constructor. After initializing some of the basic display properties that relate to the JTree superclass and the DOM parsing objects, the constructor builds a TreeModel object to create the actual visual tree. To do this, a root node is created by passing the DOM object into the createTreeNode() method which returns an object of type DefaultMutableTreeNode. This object is then used to create the tree’s TreeModel via the setModel() method inherited from the JTree class.
- private DefaultMutableTreeNode createTreeNode( Node root )?This method takes a DOM Node and recurses through the children until each one is added to a DefaultMutableTreeNode. This is a recursive method, calling itself for each child node found beneath the root node. The JTree then uses the DefaultMutableTreeNode object as a tree model.
- private String getNodeType( Node node ) ?This method is used by createTreeNode() to associate a string of text with a particular type of node.
- private Node parseXml()?This method performs the actual parsing of the XML text string. It returns an object of type Node that can then be passed into the createTreeNode() method.
There you have it: a class that extends JTree, adding XML text parsing capabilities. In the next two articles we will build additional components and extend upon this component to create a simple, platform-independent XML editor.
Below, you will find links to two java source files, a sample XML file, and the xerces.jar with the JAXP classes and Xerces parser. To experiment with the XTree class, follow the following steps:
- download the four files;
- make sure the xerces.jar file is in your classpath;
- compile the two java source files;
- run the XTreeTester class and pass the sample XML file as an argument like this: java XTreeTester sample.xml
XTree.java?The XTree component class.
XTreeTester.java?This file contains a main() method and is used to test the XTree class by parsing an XML file.
Sample.xml?A sample XML file to pass into the XTreeTester class.
xerces.jar?This jar file contains the Xerces parser and the JAXP classes required by the XTree class. It must be in your classpath for the application to successfully compile and execute.