2011年11月14日 星期一

Simple XML parser use sax

This is a small XML parser using sax.

If you only have one or two xmls to handle in your system, it's quick and simple.

import java.io.ByteArrayInputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.builder.ToStringBuilder; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory; public class MyParser { public static void main(String... args) { String xml = "<root>" + "<employee><name>David</name><phone>1234</phone></employee>"+ "<employee><name>Luke</name><phone>9998</phone></employee>"+ "<employee><name>Mark</name><phone>5678</phone></employee>"+ "</root>"; MyParser parser = new MyParser(); List result = parser.parse(new ByteArrayInputStream(xml.getBytes())); for(Employee e : result){ System.out.println(e); } } public List parse(InputStream inputStream) { try { XMLReader xmlReader = XMLReaderFactory.createXMLReader(); EmployeeHandler handler = new EmployeeHandler(); xmlReader.setContentHandler(handler); xmlReader.parse(new InputSource(inputStream)); return handler.getEmployeeList(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null; } private class EmployeeHandler extends DefaultHandler { private CharArrayWriter contents = new CharArrayWriter(); private List employeeList = new ArrayList(); private String ename; private String ephone; public List getEmployeeList() { return employeeList; } @Override public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException { contents.reset(); } @Override public void endElement(String uri, String localName, String name) throws SAXException { if ("name".equals(localName)) { ename = contents.toString(); return; } if ("phone".equals(localName)) { ephone = contents.toString(); return; } if("employee".equals(localName)){ Employee e = new Employee(); e.setName(ename); e.setPhone(ephone); employeeList.add(e); return; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { contents.write(ch, start, length); } } }
Employee POJO
class Employee { private String name; private String phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String toString(){ return ToStringBuilder.reflectionToString(this); } }

Copy function of PostgreSQL

One of my projects need to insert million records into database (postgreSQL). The performance becomes the key factor. Using the traditional insert statement will take a few days!

We are lucky that postgreSQL provides a very useful function for bulk insert.

import org.postgresql.copy.CopyManager; import org.postgresql.core.BaseConnection; import java.sql.Connection; StringBuilder csvContent = new StringBuilder(); //create your csv content here, or read from a file. Connection conn = //get your connection from datasource CopyManager copyManager = new CopyManager((BaseConnection) conn); long affected = copyManager.copyIn("COPY table FROM STDIN WITH csv header", new ByteArrayInputStream(csvContent.toString().getBytes())); LOG.debug("Copy from csv completed. Insert " + affected + " records.");

Dynamic Comparator

Java provides Comparable interface to help you sort the items in the collections. However, if you want to dynamically decide the field to sort the collection, try this dynamic comparator
import java.lang.reflect.Method; import java.util.Comparator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class DynamicComparator<T> implements Comparator<T> { private static final Log LOG = LogFactory.getLog(DynamicComparator.class); private final Class[] nullclazz = new Class[] {}; private final Object[] nullargs = new Object[] {}; private Method method; private String returnType; public DynamicComparator(Class class1, String fieldName) throws SecurityException, NoSuchMethodException { this.method = getMethod(class1, "get", fieldName); this.returnType = method.getReturnType().getName(); } public int compare(T o1, T o2) { if (o1 == null && o2 == null) { return 0; } else if (o1 == null || o2 == null) { return o1 == null ? -1 : 1; } else { try { if ("java.lang.String".equals(returnType)) { return ((String) method.invoke(o1, nullargs)) .compareTo((String) method.invoke(o2, nullargs)); } if ("int".equals(returnType)) { return ((Integer) method.invoke(o1, nullargs)) .compareTo((Integer) method.invoke(o2, nullargs)); } if ("double".equals(returnType)) { return ((Double) method.invoke(o1, nullargs)) .compareTo((Double) method.invoke(o2, nullargs)); } } catch (Exception e) { LOG.error(e); } } return 0; } private Method getMethod(Class clazz, String prefix, String fieldName) { String methodName = prefix + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1); try { return clazz.getMethod(methodName, nullclazz); } catch (Exception e) { LOG.error(e); } return null; } }
To use this class:
Collection c = //the collection you want to sort. List list = new ArrayList(c); DynamicComparator comparator = new DynamicComparator(list.get(0).getClass(), "fieldName"); Collections.sort(list, comparator);