4.2. Setting Up a Simple XML DocumentBefore we delve into the code, we need to make some decisions. We're going to return data using XML, but how should that XML be structured? What should our XML response look like? We don't want anything complex, so we'll aim to create an XML document that looks like this: <converted-values> <decimal>97</decimal> <hexadecimal>0x61</hexadecimal> <octal>0141</octal> <hyper>&0x61;</hyper> <binary>1100001B</binary> </converted-values> With this format, the browser can use its document object model (DOM) parser to index and retrieve the data. There are many ways to create this XML document. For the sake of simplicity, we'll first use a StringBuffer to wrap the data with XML tags. Later, we'll look at other ways to create the XML document.
4.2.1. Using a Servlet to Build an XML DocumentLet's start by looking at the servlet code that wraps the data in XML. This servlet is shown in Example 4-1. Example 4-1. The AjaxResponseServlet
This code is similar to the code from Chapter 3. The only thing that has been added is the code to wrap the data with XML tags: returnXML = new StringBuffer("\r\n<converted-values>"); returnXML.append("\r\n<decimal>"+ Integer.toString(keyInt)+"</decimal>"); returnXML.append("\r\n<hexadecimal>0x"+ Integer.toString(keyInt,16)+"</hexadecimal>"); returnXML.append("\r\n<octal>0"+ Integer.toString(keyInt,8)+"</octal>"); returnXML.append("\r\n<hyper>&0x"+ Integer.toString(keyInt,16)+";</hyper>"); returnXML.append("\r\n<binary>"+ Integer.toString(keyInt,2)+"B</binary>"); returnXML.append("\r\n</converted-values>"); This code simply sets up a StringBuffer called returnXML. We then convert the incoming value to decimal, hex, etc.; wrap it with an appropriate XML tag; and append it to the buffer. When we've finished all five conversions and added the closing tag (</converted-values>), we send the response back to the Ajax client using res.getWriter().write( ). We return a question mark (without any XML wrapping) if the key we received was null. 4.2.2. Other Ways to Build the XML DocumentBuilding an XML document by appending to a StringBuffer is a common approach, but it's far from ideal, particularly if you need to generate a large document programmatically. Fortunately, there are alternatives. 4.2.2.1. JDOMOne option is to use the JDOM library to write the XML. Download the jdom.jar file from http://www.jdom.org, and put it in your application's WEB-INF/lib directory. Then, instead of writing to a StringBuffer, use JDOM to build the XML, as shown in Example 4-2. Example 4-2. Using JDOM to create the XML document
In the preceding code, we first create a Document (org.jdom.Document), then an Element named root with the String "converted-values" as its value. That element becomes the root of the XML document. Here's what the document looks like at this point: <converted-values> </converted-values> To add child elements to the root, we create new elements and add them to the root element. The code that creates the decimal element and adds it to the root element looks like this: org.jdom.Element element = new org.jdom.Element("decimal"); element.addContent(Integer.toString(key)); root.addContent(element); We repeat this process until we've added all the elements to the root. Then we use an XMLOutputter to format the document into a String that we can send back to the client. The JDOM XML document now looks like this (with linefeeds and spaces added for readability): <?xml version="1.0" encoding="UTF-8"?> <converted-values> <decimal>97</decimal> <hexadecimal>0x61</hexadecimal> <octal>0141</octal> <hyper>&0x61</hyper> <binary>1100001B</binary> </converted-values> 4.2.2.2. dom4jdom4j is an XML library similar in intent to JDOM. After downloading dom4j from http://www.dom4j.org/download.html and installing it in your application's WEB-INF/lib directory, you can use it to create your XML document. As shown in Example 4-3, we create a document, add a root element to the document, add the elements and data to the root, and then return the document in a String. Example 4-3. Using dom4j to create the XML document
The dom4j library uses the static method DocumentHelper.createDocument( ) to create the XML document. The method root.addElement( ) puts a child element on the root element, and addText( ) puts the data in the elements. The OutputFormat class is then used to format the XMLDocument, so the document looks like this: <?xml version="1.0" encoding="UTF-8"?> <converted-values> <decimal>97</decimal> <hexadecimal>0x61</hexadecimal> <octal>0141</octal> <hyper>&0x61</hyper> <binary>1100001B</binary> </converted-values> This step can be skipped, because it only formats the document for readability by adding linefeeds and spaces. Since humans shouldn't need to read this document (unless you are debugging), you won't need the formatting. To use dom4j without the formatting, simply replace these two lines: OutputFormat outformat = OutputFormat.createPrettyPrint( ); XMLWriter writer = new XMLWriter(sw, outformat); with this line: XMLWriter writer = new XMLWriter(sw); 4.2.2.3. SAXSAX, the Simple API for XML, provides another way to create an XML document for an Ajax application. It may be faster than JDOM or dom4J, because it doesn't require building a DOM tree for your document. Start by initializing a StringWriter and a StreamResult. Initialize the StreamResult with the StreamWriter, then get a SAXTransformerFactory and get a transformerHandler from that. The TRansformerHandler allows you to create an XML document by starting a document and appending elements and data to the TRansformerHandler. Example 4-4 shows how it works. Example 4-4. Using SAX to write out the XML document
After calling startDocument( ) to begin the document, we must create the elements and add data to them. We create an element by calling startElement( ): transformerHandler.startElement(null,null,"binary",null) The third element is the only element needed to set up the XML tag, <binary>.
To put the data after the element tag, we set a String, data, to the desired value: data = Integer.toString(key, 2)+"B"; Then we convert the data to a CharArray and pass it into the characters( ) method. The second and third parameters show where processing starts and stops in the CharArray: transformerHandler.characters(data.toCharArray(),0,data.length( )); Finally, we terminate the element with a call to endElement( ): transformerHandler.endElement(null,null,"binary"); Each element is created with startElement( ), characters( ), and endElement( ). When all of the elements for the documents have been completed, a call to endDocument( ) is executed and the result is sent to the StreamResult that was set up at the start of the method: transformerHandler.endElement(null,null, "converted-values"); transformerHandler.endDocument( ); transformerHandler.setResult(streamResult); Finally, the StreamResult is converted to a String by calling toString( ) on the StringWriter. The StreamResult wraps the StringWriter that was set up at the beginning of this method: return writer.toString( ); The String can then be returned to the calling method. Using SAX is purportedly a faster and less memory-intensive way to create XML documents than using DOM-based libraries such as JDOM and dom4j. If your testing shows that speed is an issue, or if the SAX API is more natural for your application, you should consider using it.
|