Warner Technology Consulting Logo

Java Coding Part Four: XML Preferences
Now comes the most mysterious part of all: XML. XML is a term which many have heard, but which no one seems to understand. XML is basically a method for encapsulating data with descriptive tags. So, unlike HTML which mostly describes how to format the data, XML’s tags describe what the data is (a price, a link, etc). Why use XML in a preferences file? So the data does not have to reside in any particular order; its tags make it clear what type of data it is.

Well-formed, validated XML files are regulated by a descriptor file (DTD). Here’s the DTD file for this project. I won’t try to explain all the syntax here. For a tutorial on XML, a place to start is IBM’s Alphaworks site (http://www-4.ibm.com/software/developer/education/tutorial-prog/writing.html).



<?xml encoding="US-ASCII"?>

<!ELEMENT myFetchAppPrefs ( ProxyInfo*, SiteInfo+ ) >

<!ELEMENT ProxyInfo EMPTY >
<!ATTLIST ProxyInfo
IP CDATA #REQUIRED
Port CDATA #REQUIRED
username CDATA #IMPLIED
pass CDATA #IMPLIED>

<!ELEMENT SiteInfo EMPTY >
<!ATTLIST SiteInfo
url CDATA #REQUIRED
username CDATA #IMPLIED
password CDATA #IMPLIED>

Now that we have the descriptor file, it becomes a matter of entering the data into an XML file. I used IBM’s free Xeena to create the XML file, although it requires some work to get installed and running properly. The file is just plain text, so it can also be edited with any text editor, if you elect to go that route.



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE EnergyFetchAppPrefs SYSTEM "myFetchAppPrefs.dtd" >
<myFetchAppPrefs>
<ProxyInfo Port="8080" IP="192.168.34.44"/>
<SiteInfo url="https://store.sun.com"/>
<SiteInfo url="http://www.apple.com"/>
<SiteInfo url="ftp://nerctagftp.nerc.com/active/CA%20sheet.csv"/>
</myFetchAppPrefs>

Note that the last entry is an FTP site and that the filename we want to retrieve has a space in it. While this is considered poor form, you can get around it by using the %20 symbol instead of the space. If you wanted to include a username and password the entry would look like:

<SiteInfo url="http://www.somesite.com" username=”username” password=”pass”/>

Likewise with the proxy info, should you require a username and password there:

<ProxyInfo Port="8080" IP="192.168.34.44" username=”username” pass=”pass”/>

To parse the XML file from within our Java code, we open the document and parse it using both W3- and IBM-provided classes:


DOMParser parser = new DOMParser();
parser.parse(filename);
Document document = parser.getDocument();
Element root = (Element)document.getDocumentElement();

Then we take the Element root (which is actually a node) and traverse the branch, one node at a time and take the data as it comes. In this sample application, I have chosen to allocate an array of SiteObjects (part three); not the most elegant approach, but hey, this is just a sample app, right? We only need a single ProxyObject since that will not change for a given machine. Note that when you declare (instantiate) an array of a custom object type, you have to then allocate memory (instantiate). I chose to do this in the init() function in the final code.



NamedNodeMap theMap=null;
Node pointer=null;
int counter=0;

if (node.hasChildNodes()) {
NodeList nl = node.getChildNodes();
int size = nl.getLength();
for (int i = 0; i < size; i++) {
theMap=nl.item(i).getAttributes(); // does this node have any attributes (data, in our case)?
if (theMap!=null) { // Is there any information to get from this node?

if (nl.item(i).getNodeName().equalsIgnoreCase("proxyinfo")) { // we've got proxy info!
for (int x=0; x<theMap.getLength(); x++) {

// get the proxy values and stuff them into the object
if (theMap.item(x).getNodeName().equalsIgnoreCase("port"))
proxyInfo.ProxyPort=theMap.item(x).getNodeValue();
if (theMap.item(x).getNodeName().equalsIgnoreCase("ip"))
proxyInfo.ProxyServer=theMap.item(x).getNodeValue();
if (theMap.item(x).getNodeName().equalsIgnoreCase("username"))
proxyInfo.username=theMap.item(x).getNodeValue();
if (theMap.item(x).getNodeName().equalsIgnoreCase("pass"))
proxyInfo.password=theMap.item(x).getNodeValue();
} // for
} // if=proxyinfo

else if (nl.item(i).getNodeName().equalsIgnoreCase("siteinfo")) {
// Site Information. Note that we ignore any other Node Names (types)
for (int x=0; x<theMap.getLength(); x++) {
// get the site values and stuff them into the object
if (theMap.item(x).getNodeName().equalsIgnoreCase("url"))
siteInfo[counter].URL=theMap.item(x).getNodeValue();
if (theMap.item(x).getNodeName().equalsIgnoreCase("username"))
siteInfo[counter].username=theMap.item(x).getNodeValue();
if (theMap.item(x).getNodeName().equalsIgnoreCase("password"))
siteInfo[counter].password=theMap.item(x).getNodeValue();
} // for
counter++; // keep track!
if (counter>gArrayLength) {
System.out.println("Error: More sites than space available.”+
“ Please increase the size of the gArrayLength variable.");
return;
}
} // else if=siteinfo

} // if theMap!=null
} // for i<size
} // if has child nodes
}

Although this might seem like a bit of work, the one real advantage is that we can take an XML file generated by anyone, using any XML software, as long as they used our DTD file, and the information can be entered in any order.


Previous SectionNext Section


Business Text
Automotive Text
Computers Text
Site Search
Made with Macintosh!
Site by Warner Technology Consulting. All material is copyright 1999. If you reference material on this site, you are expected to annotate the source from which it came. That is, you may use information on this site, but you must clearly state from where you obtained it.
Page last updated on Tue, May 16, 2000

Text Links: BusinessAutomotiveComputerSGI
Mac OS X ServerMacintosh • Matt's Hack TV
Software • PS on Non-PS Printers • Porsche

R E A D E R • C O M M E N T S
Add a Comment