Converting the code we've written to display a document in a window isn't difficult because that code was purposely written to store the output in an array of strings and because I can display those strings in a Java window. In this example, I'll upgrade that code to a new program, browser.java, that will use Java to display XML documents in a window. Here's how it works. I start by parsing the document the user wants to parse in the main method: public static void main(String args[]) { displayDocument(args[0]); . . . Then I'll create a new window using the techniques we saw in the previous chapter. Specifically, I'll create a new class named AppFrame , create an object of that class, and display it: public static void main(String args[]) { displayDocument(args[0]); AppFrame f = new AppFrame(displayStrings, numberDisplayLines); f.setSize(300, 500); f.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}}); f.show(); } The AppFrame class is specially designed to display the output strings in the displayStrings array in a Java window. To do that, I pass that array and the number of lines to display to the AppFrame constructor, and I store them in this new class: class AppFrame extends Frame { String displayStrings[]; int numberDisplayLines; public AppFrame(String[] strings, int number) { displayStrings = strings; numberDisplayLines = number; } . . . All that's left is to display the strings in the displayStrings array. When you display text in a Java window, you're responsible for positioning that text as you want it. To display multiline text, we'll need to know the height of a line of text in the window, and you can find that with the Java FontMetrics class's getHeight method. Here's how I display the output text in the AppFrame window. I create a new Java Font object using Courier font, and I install it in the Graphics object passed to the paint method. Then I find the height of each line of text: public void paint(Graphics g) { Font font = new Font("Courier", Font.PLAIN, 12); g.setFont(font); FontMetrics fontmetrics = getFontMetrics(getFont()); int y = fontmetrics.getHeight(); . . . Finally, I loop over all lines of text using the Java Graphics object's drawString method: public void paint(Graphics g) { Font font = new Font("Courier", Font.PLAIN, 12); g.setFont(font); FontMetrics fontmetrics = getFontMetrics(getFont()); int y = fontmetrics.getHeight(); for(int index = 0; index < numberDisplayLines; index++){ y += fontmetrics.getHeight(); g.drawString(displayStrings[index], 5, y); } } You can see the result in Figure 11-3. As you see in this figure, ch11_01.xml is displayed in our windowed browser. Figure 11-3. A graphical browser.
Here's the code for this example, ch11_05.java: Listing ch11_05.javaimport javax.xml.parsers.*; import org.w3c.dom.*; import java.awt.*; import java.awt.event.*; public class ch11_05 { static String displayStrings[] = new String[1000]; static int numberDisplayLines = 0; public static void displayDocument(String uri) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = null; try { db = dbf.newDocumentBuilder(); } catch (ParserConfigurationException pce) {} Document document = null; document = db.parse(uri); display(document, ""); } catch (Exception e) { e.printStackTrace(System.err); } } public static void display(Node node, String indent) { if (node == null) { return; } int type = node.getNodeType(); switch (type) { case Node.DOCUMENT_NODE: { displayStrings[numberDisplayLines] = indent; displayStrings[numberDisplayLines] += "<?xml version=\"1.0\" encoding=\""+ "UTF-8" + "\"?>"; numberDisplayLines++; display(((Document)node).getDocumentElement(), ""); break; } case Node.ELEMENT_NODE: { displayStrings[numberDisplayLines] = indent; displayStrings[numberDisplayLines] += "<"; displayStrings[numberDisplayLines] += node.getNodeName(); int length = (node.getAttributes() != null) ? node.getAttributes(). getLength() : 0; Attr attrs[] = new Attr[length]; for (int loopIndex = 0; loopIndex < length; loopIndex++) { attrs[loopIndex] = (Attr)node.getAttributes().item(loopIndex); } for (int loopIndex = 0; loopIndex < attrs.length; loopIndex++) { Attr attr = attrs[loopIndex]; displayStrings[numberDisplayLines] += " "; displayStrings[numberDisplayLines] += attr.getNodeName(); displayStrings[numberDisplayLines] += "=\""; displayStrings[numberDisplayLines] += attr.getNodeValue(); displayStrings[numberDisplayLines] += "\""; } displayStrings[numberDisplayLines] +=">"; numberDisplayLines++; NodeList childNodes = node.getChildNodes(); if (childNodes != null) { length = childNodes.getLength(); indent += " "; for (int loopIndex = 0; loopIndex < length; loopIndex++ ) { display(childNodes.item(loopIndex), indent); } } break; } case Node.CDATA_SECTION_NODE: { displayStrings[numberDisplayLines] = indent; displayStrings[numberDisplayLines] += "<![CDATA["; displayStrings[numberDisplayLines] += node.getNodeValue(); displayStrings[numberDisplayLines] += "]]>"; numberDisplayLines++; break; } case Node.TEXT_NODE: { displayStrings[numberDisplayLines] = indent; String newText = node.getNodeValue().trim(); if(newText.indexOf("\n") < 0 && newText.length() > 0) { displayStrings[numberDisplayLines] += newText; numberDisplayLines++; } break; } case Node.PROCESSING_INSTRUCTION_NODE: { displayStrings[numberDisplayLines] = indent; displayStrings[numberDisplayLines] += "<?"; displayStrings[numberDisplayLines] += node.getNodeName(); String text = node.getNodeValue(); if (text != null && text.length() > 0) { displayStrings[numberDisplayLines] += text; } displayStrings[numberDisplayLines] += "?>"; numberDisplayLines++; break; } } if (type == Node.ELEMENT_NODE) { displayStrings[numberDisplayLines] = indent.substring(0, indent.length() - 4); displayStrings[numberDisplayLines] += "</"; displayStrings[numberDisplayLines] += node.getNodeName(); displayStrings[numberDisplayLines] +=">"; numberDisplayLines++; indent+= " "; } } public static void main(String args[]) { displayDocument(args[0]); AppFrame f = new AppFrame(displayStrings, numberDisplayLines); f.setSize(300, 500); f.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}}); f.show(); } } class AppFrame extends Frame { String displayStrings[]; int numberDisplayLines; public AppFrame(String[] strings, int number) { displayStrings = strings; numberDisplayLines = number; } public void paint(Graphics g) { Font font = new Font("Courier", Font.PLAIN, 12); g.setFont(font); FontMetrics fontmetrics = getFontMetrics(getFont()); int y = fontmetrics.getHeight(); for(int index = 0; index < numberDisplayLines; index++){ y += fontmetrics.getHeight(); g.drawString(displayStrings[index], 5, y); } } } Now that we're parsing and displaying XML documents in windows , there's no reason to restrict ourselves to displaying the text form of an XML document. Take a look at the next topic. |