Create the XmlEditor Class
The XmlEditor class serves the same purpose as the XTreeTester class did in the previous article. The difference is that the XmlEditor will include a JTextArea that will allow you to manipulate a text version of the XML. After that, you can click the "Refresh" button and see the changes reflected in the XTree component.
If you're modifying the code from the last article, you will have a much easier time if you rename the XTreeTester.java file to XmlEditor.java (be sure and modify the constructor) and use that as a template.
The first thing to do is to add the following Swing components: another JScrollPane, a JSplitPane, a JTextArea, and a JButton. Start by declaring all of these with the other component declarations. (See Listing 3.)
First, we'll create and add the "Refresh" button. This button will be used to indicate that the XTree component should be refreshed with the current XML text. We'll also need to register it with an ActionListener. (See Listing 4.) In order to intercept button events, we will need to have this class also implement ActionListener, and we will need to create an actionPerformed() method. (See Listing 5.)
Next, we'll create the new JScrollPane and the JTextArea and add the JTextArea to the JScrollPane. Thus, we will have the original JScrollPane containing the XTree component and the new JScrollPane containing the JTextArea component. There is one modification to make to the original XTree constructor. We will remove the String parameter that we previously passed into this method. (That functionality is handled by the other XmlEditor() constructor that we will build next.) We'll put both of these panes in a JSplitPane, which is a component that has a divider and can house one component on either side of the divider. (See Listing 6.)
Now we need to modify the constructors to handle the no-XML file scenario. Remove the second String parameter that the current constructor is expecting. This constructor will now be the default constructor. Instead, we will create a new constructor that accepts a single string parameter. It will first call the default constructor, and then process the parameter. (See Listing 7.) Also, the main() method must be changed so that in the event that no XML file is provided, a default XmlEditor object will still be created. (See Listing 8.)
There is one last change necessary in order to handle the JTextArea data easily. Rather than treating the text contained within it as one long string, we will treat it as a series of strings, with each line representing a string contained within an ArrayList. This will require modifying the parameter accepted by our constructor, as well as modifying any calls within the main() method that previously passed this data as a String. This will also require importing the java.util package. (See Listing 8.)
Testing the Application
Finally, we must add a bit of exception handling to the XTree class. If you were to run the application as this point and enter invalid XML data in the JTextArea, the program would crash. We don't want that to happen. For now, we will have the error message print to the command line. In the next article, we will have the error message display in a graphical dialogue box.
If invalid or non-well-formed XML data is entered into the JTextArea and the "Refresh" button pushed, then the parser will spit out an error. The current exception handling contained in the parseXML() method will immediately exit in this case. Instead, we want the program to report the error and return a null value to indicate that the parsing was unsuccessful. (See Listing 9.) You may have noticed that both the "buildTree()" and "refresh()" methods in the XTree class have a conditional statement that avoids processing a null value. This is because they too would report exceptions if they tried to process a null value. This chain of events keeps the program flow going and the XTree model stable.
Finally, we are ready to test the application. You should see something like this: (See Figure 1.)
Congratulations! We'll put the finishing touches to this tool in the third and final article.