package org.kobjects.xmlrpc; /** * @author Stefan Haustein * * <p>A simple XML RPC parser based on the XML PULL API, * intended to show the XMLPULL and KXml2 API usage with * a real application example.</p> * * <ul> * <li>For the XML RPC specification, please refer to * <a href="http://www.xmlrpc.com/spec">http://www.xmlrpc.com/spec</a></li> * <li>For the XmlPullParser API specification, please refer to * <a href="http://xmlpull.org/">xmlpull.org</a></li> * <li>For information about kXML 2, please refer to * <a href="http://kxml.org/">kxml.org</a></li> * </ul> */ import java.util.*; import java.io.*; import org.xmlpull.v1.*; public class XmlRpcParser { XmlPullParser parser; /** * Creates a new XmlRpcParser, using the given XmlPullParser. */ public XmlRpcParser(XmlPullParser parser) { this.parser = parser; } /** * Parses an XML RPC method call response. * The return values are collected in a Vector. * * @return The return values collected in a Vector. */ public Vector parseResponse() throws XmlPullParserException, IOException { Vector result = new Vector(); parser.nextTag(); parser.require(parser.START_TAG, "", "methodResponse"); parser.nextTag(); parser.require(parser.START_TAG, "", "params"); while (parser.nextTag() == parser.START_TAG) { parser.require(parser.START_TAG, "", "param"); parser.nextTag(); result.addElement(parseValue()); parser.nextTag(); parser.require(parser.END_TAG, "", "param"); } parser.require(parser.END_TAG, "", "params"); parser.nextTag(); parser.require(parser.END_TAG, "", "methodResponse"); parser.next(); parser.require(parser.END_DOCUMENT, null, null); return result; } /** * Parses an XML-RPC value element. Returns the * content of the element as a corresponding Java object. * <p> * <b>precondition:</b> parser is on a "value" start tag<br /> * <b>postcondition:</b> parser is on a "value" end tag</p> */ Object parseValue() throws IOException, XmlPullParserException { parser.require(parser.START_TAG, "", "value"); // precondition parser.next(); Object result; if (parser.getEventType() == parser.END_TAG) result = ""; else if (parser.getEventType() == parser.TEXT) { result = parser.getText(); parser.nextTag(); } else { parser.require(parser.START_TAG, "", null); String name = parser.getName(); if (name.equals("double")) result = new Double(parser.nextText()); else if (name.equals("int") || name.equals("i4")) result = new Integer(parser.nextText()); else if (name.equals("array")) result = parseArray(); else if (name.equals("string")) result = parser.nextText(); else if (name.equals("struct")) result = parseStruct(); else throw new RuntimeException("unexpected element: " + name); parser.require(parser.END_TAG, "", name); parser.nextTag(); } parser.require(parser.END_TAG, "", "value"); // postcond. return result; } /** Parses an XML-RPC array and returns it as a Java Vector * * <p> * <b>Precondition:</b> On "array" start tag<br /> * <b>Postcondition:</b> On "array" end tag * </p> */ Vector parseArray() throws IOException, XmlPullParserException { Vector v = new Vector(); parser.require(parser.START_TAG, "", "array"); while (parser.nextTag() == parser.START_TAG) v.addElement(parseValue()); parser.require(parser.END_TAG, "", "array"); return v; } Hashtable parseStruct() throws IOException, XmlPullParserException { Hashtable struct = new Hashtable(); parser.require(parser.START_TAG, "", "struct"); while (parser.nextTag() == parser.START_TAG) { parser.require(parser.START_TAG, "", "member"); parser.nextTag(); parser.require(parser.START_TAG, "", "name"); String name = parser.nextText(); parser.require(parser.END_TAG, "", "name"); parser.nextTag(); struct.put(name, parseValue()); parser.nextTag(); parser.require(parser.END_TAG, "", "member"); } parser.require(parser.END_TAG, "", "struct"); return struct; } /** main method, temporarily included for simple testing only */ public static void main(String[] argv) throws IOException, XmlPullParserException { String test = "<?xml version=\"1.0\"?>\n" + "<methodResponse><params>\n" + " <param>\n" + " <value><string>South Dakota</string></value>\n" + " </param><param>\n" + " <value><struct>\n" + " <member><name>foo</name><value>bar</value></member>\n" + " <member><name>v</name><value><array></array></value></member>\n" + " </struct></value>\n" + " </param><param>\n" + " <value><double>3.14</double></value>\n" + " </param>\n" + "</params></methodResponse>\n"; System.out.println("test input:\n" + test); XmlPullParser xp = new org.kxml2.io.KXmlParser(); xp.setInput(new java.io.StringReader(test)); System.out.println( "parsing result: " + new XmlRpcParser(xp).parseResponse()); } }