In Java, text is just a form of graphics, so we've already been
working with graphics. In this next example, I'll create a nontext
browser that reads an XML document and uses it to draw graphics
figures-circles. Here's what a document this browser might read,
circles.xml, looks like-I'm specifying the (x, y) origin of the
circle and the radius of the circle as attributes of the
<CIRCLE> element:
<?xml version = "1.0" ?>
<!DOCTYPE DOCUMENT [
<!ELEMENT DOCUMENT (CIRCLE|ELLIPSE)*>
<!ELEMENT CIRCLE EMPTY>
<!ELEMENT ELLIPSE EMPTY>
<!ATTLIST CIRCLE
X CDATA #IMPLIED
Y CDATA #IMPLIED
RADIUS CDATA #IMPLIED>
<!ATTLIST ELLIPSE
X CDATA #IMPLIED
Y CDATA #IMPLIED
WIDTH CDATA #IMPLIED
HEIGHT CDATA #IMPLIED>
]>
<DOCUMENT>
<CIRCLE X='200' Y='160' RADIUS='50'
/>
<CIRCLE X='170' Y='100' RADIUS='15'
/>
<CIRCLE X='80' Y='200' RADIUS='45' />
<CIRCLE X='200' Y='140' RADIUS='35'
/>
<CIRCLE X='130' Y='240' RADIUS='25'
/>
<CIRCLE X='270' Y='300' RADIUS='45'
/>
<CIRCLE X='210' Y='240' RADIUS='25'
/>
<CIRCLE X='60' Y='160' RADIUS='35' />
<CIRCLE X='160' Y='260' RADIUS='55'
/>
</DOCUMENT>
I'll call this example circles.java. We'll need to decode the XML
document and store the specification of each circle. To store that
data, I'll create an array named x to hold the x coordinates of the
circles, y to hold the y coordinates, and radius to hold the radii of
the circles. I'll also store our current location in these arrays in
an integer named numberFigures:
public class circles
{
static int numberFigures = 0;
static int x[] = new int[100];
static int y[] = new int[100];
static int radius[] = new int[100];
.
.
.
As we parse the document, I'll filter out elements and search for
<CIRCLE> elements. When I find a <CIRCLE> element, I'll
store its x, y, and radius values in the appropriate array. To check
whether the current node is a <CIRCLE> element, I'll compare
the node's name, which I get with the getNodeName method, to "CIRCLE"
using the Java String method equals, which you must use with String
objects instead of the == operator:
if (node.getNodeType() == Node.ELEMENT_NODE) {
if
(node.getNodeName().equals("CIRCLE")) {
.
.
.
}
.
.
.
To find the value of the X, Y, and RADIUS attributes, I'll use the
getAttributes method to get a NamedNodeMap object representing all
the attributes of this element. To get the value of specific
attributes, I get the node corresponding to that attribute with the
getNamedItem method. I get the attribute's actual value with
getNodeValue like this, where I'm converting the attribute data from
strings to integers using the Java Integer class's parseInt
method:
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.getNodeName().equals("CIRCLE")) {
NamedNodeMap attrs =
node.getAttributes();
x[numberFigures] =
Integer.parseInt((String)attrs.getNamedItem("X").getNodeValue());
y[numberFigures] =
Integer.parseInt((String)attrs.getNamedItem("Y").getNodeValue());
radius[numberFigures]
=
Integer.parseInt((String)attrs.getNamedItem("RADIUS").getNodeValue());
numberFigures++;
}
.
.
.
You can find the methods of the NamedNodeMap interface in Table
11.7.
NamedNodeMap Interface Methods
Method
Description
int
getLength()
Returns the number of nodes in this map
Node getNamedItem(java.lang.String
name)
Gets a node indicated by name
Node getNamedItemNS(java.lang.String
Gets a node indicated by a local name and namespaceURI,
java.lang.String
localName)
namespace URI
Node item(int
index)
Gets an item in the map by index
Node
removeNamedItem
Removes a node given by name(java.lang.String name)
Node
removeNamedItemNS(java.lang.
Removes a node given by a local name and String namespaceURI,
java.lang.S namespace URItring localName)
Node setNamedItem(Node
arg)
Adds a node specified by its nodeName attribute
Node setNamedItemNS(Node
arg)
‑Adds a node specified by its namespaceURI and localName
After parsing the document, the required data is in the x, y, and
radius arrays. All that's left is to display the corresponding
circles, and I'll use the Java Graphics object's drawOval method to
do that. This method draws ellipses and takes the (x, y) location of
the figure's origin, as well as the minor and major axes' length. To
draw circles, I'll set both those lengths to the radius value for the
circle. It all looks like this in the AppFrame class, which is where
we draw the browser's window:
class AppFrame extends Frame
{
int numberFigures;
int[] xValues;
int[] yValues;
int[] radiusValues;
public AppFrame(int number, int[] x, int[] y,
int[] radius)
{
numberFigures =
number;
xValues = x;
yValues = y;
radiusValues =
radius;
}
public void paint(Graphics g)
{
for(int loopIndex = 0;
loopIndex < numberFigures; loopIndex++){
g.drawOval(xValues[loopIndex], yValues[loopIndex],
radiusValues[loopIndex], radiusValues[loopIndex]);
}
}
And that's all it takes; you can see the results in Figure 11.4,
where the browser is displaying circles.xml. The complete listing
appears in Listing 11.4.