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; I can display those strings
in a Java window. In this example, I'll upgrade that code to a new
program, browser.java, which will use XML for Java to display XML
documents in a window.
Here's how it works; I start by parsing the document that 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've seen 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 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 install it in
the Graphics object passed to the paint method. Then I find the
height of each line of plain 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 that figure,
customer.xml is displayed in our windowed browser. The code for this
example, browser.java, appears in Listing 11.3.
A graphical browser.
browser.java
import java.awt.*;
import java.awt.event.*;
import org.w3c.dom.*;
import org.apache.xerces.parsers.DOMParser;
public class browser
{
static String displayStrings[] = new
String[1000];
static int numberDisplayLines = 0;
public static void displayDocument(String
uri)
{
try {
DOMParser parser = new DOMParser();
parser.parse(uri);
Document document = parser.getDocument();
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.