夜已经深了,可是我仍未眠。明天就要回家过年了,对于一个飘荡在外的游子来说,回家过年是一件多么激动人心的事啊!这才是我心中真正的年啊! 真希望新的一年快点到来,因为有太多的不愉快需要忘记、因为有太多的梦想需要去实现……
前一段时间要解析一个XML文件,就是对XML进行增、删、改的操作。以前做J2EE时一直都是用第三方的类库来辅助解决的,但这次却要求自己用DOM来解析,只能用JDK自带的类库! 一直到现在还没有想通:为什么要重复发明轮子呢???但是事情还是要做的,我只是俗人,我也要吃饭…… 又或许,这只是我的又一个自我解嘲的借口罢了!
下边的类其实有很多不足的地方的,但我却始终不能说服我自己, 我就是这样一个倔强又刚愎自用的人,期待来年吧,希望走过本命年的我能成熟起来,对于一些事情的控制更自由一些。。。
import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.StringTokenizer;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList;
/** * <p>ConfigParser</p> * 1. read the config XML,or update the file.</br> * 2. query a property from the config file,the property name fromat:lss.agent.version etc.</br> * 3. add properties into the config file.</br> * * <p>@author javer QQ:84831612</p> */ public class ConfigParser { private File xmlFile = null;
private Document doc = null;
private Element root = null;
public ConfigParser(String filename) { xmlFile = new File(filename); try { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); doc = builder.parse(xmlFile); root = doc.getDocumentElement(); } catch(Exception e) { System.err.println("Error creating XML parser in ConfigParser.java"); e.printStackTrace(); } }
/** * Return the value of the specified property. * * @param name the name of the property to get. * @return the value of the specified property. */ public String getValue(String name) { String[] propName = parsePropertyName(name); NodeList nodes = root.getElementsByTagName(propName[0]); if(nodes == null || nodes.getLength() < 1) return null; for(int i = 1; i < propName.length; i++) { nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]); if(nodes == null || nodes.getLength() < 1) return null; } Node node = nodes.item(0).getChildNodes().item(0); if(node != null) return node.getNodeValue(); else return null; } /** * <p>Add the values by the specified properties.</p> * For example:</br> * if values is existed as follow</br> * x.y.z1=1</br> * .z2=2</br> * .z3=3</br> * and now, you need add new values as a new group,like as follow values</br> * x.y.z1=11</br> * .z2=22</br> * .z3=33</br> * you need call this function like as follow:</br> * addValue("x.y",new String[]{"z1","z2","z3"},new String[]{"11","22","33"})</br> * and the XML will have a result as follow:</br> * <xml> * <x> * <y> * <z1>1</z1> * <z2>2</z2> * <z2>3</z2> * </y> * <y> * <z1>11</z1> * <z2>22</z2> * <z2>33</z2> * </y> * </x> * </xml> * * @param parentName * @param subNames * @param values */ public void addValue(String parentName, String[] subNames, String[] values) { String[] propName = parsePropertyName(parentName);
NodeList nodes = root.getElementsByTagName(propName[0]); if(nodes == null || nodes.getLength() < 1) { root.appendChild(doc.createElement(propName[0])); nodes = root.getElementsByTagName(propName[0]); } Element tempElement = ((Element)nodes.item(0)); for(int i = 1; i < propName.length - 1; i++) { tempElement = ((Element)nodes.item(0)); nodes = tempElement.getElementsByTagName(propName[i]); if(nodes == null || nodes.getLength() < 1) { tempElement.appendChild(doc.createElement(propName[i])); nodes = tempElement.getElementsByTagName(propName[i]); } }
tempElement = (Element)tempElement.appendChild(doc.createElement(propName[propName.length - 1])); Node node = null; for(int i = 0; i < subNames.length; i++) { node = tempElement.appendChild(doc.createElement(subNames[i])); node.appendChild(doc.createTextNode(values[i])); }
store(); }
/** * Update the value of the specified property. * @param name * @param value */ public void updateValue(String name, String value) { String[] propName = parsePropertyName(name);
NodeList nodes = root.getElementsByTagName(propName[0]); if(nodes == null || nodes.getLength() < 1) return; for(int i = 1; i < propName.length; i++) { nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]); if(nodes == null || nodes.getLength() < 1) return; }
Node node = nodes.item(0).getChildNodes().item(0); if(node != null) node.setNodeValue(value); else return;
store(); }
/** * Deletes the specified property. * * @param name the property to delete. */ public void deleteProperty(String name) { String[] propName = parsePropertyName(name); if(propName.length == 1) root.removeChild(root.getElementsByTagName(propName[0]).item(0)); else { NodeList nodes = root.getElementsByTagName(propName[0]); for(int i = 1; i < propName.length - 1; i++) { nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]); if(nodes == null || nodes.getLength() < 1) return; }
nodes.item(0).removeChild(((Element)nodes.item(0)).getElementsByTagName( propName[propName.length - 1]).item(0)); }
store(); }
/** * Return all children property names of a parent property as a String array, * or an empty array if the if there are no children. For example, given * the properties <tt>X.Y.A</tt>, <tt>X.Y.B</tt>, and <tt>X.Y.C</tt>, then * the child properties of <tt>X.Y</tt> are <tt>A</tt>, <tt>B</tt>, and * <tt>C</tt>. * * @param parent the name of the parent property. * @return all child property values for the given parent. */ public String[] getChildrenProperties(String parent) { String[] propName = parsePropertyName(parent); NodeList nodes = root.getElementsByTagName(propName[0]); if(nodes == null || nodes.getLength() < 1) return null; for(int i = 1; i < propName.length; i++) { nodes = ((Element)nodes.item(0)).getElementsByTagName(propName[i]); if(nodes == null || nodes.getLength() < 1) return null; }
nodes = nodes.item(0).getChildNodes(); ArrayList list = new ArrayList(); for(int i = 0; i < nodes.getLength(); i++) { if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE) list.add(nodes.item(i).getNodeName()); }
if(list == null) return null; else return (String[])list.toArray(new String[list.size()]); }
/** * Return the value when the specified property key and value is existent, * and return null if the specified property key and value is not existent * * @param name * @param value * @return */ public String findValue(String name, String value) { String[] propName = parsePropertyName(name); return findValue(root, 0, propName, value); }
private String findValue(Element element, int depth, String[] propName,String value) { String _value = null; if(depth == propName.length) { _value = element.getChildNodes().item(0).getNodeValue(); if(_value.equals(value)) return value; else return null; }
NodeList children = element.getElementsByTagName(propName[depth]); if(children == null || children.getLength() < 1) return null; else ++depth;
for(int i = 0; i < children.getLength(); i++) { if(children.item(i).getNodeType() != Node.ELEMENT_NODE) continue;
element = (Element)children.item(i); _value = findValue(element, depth, propName, value); if(_value != null) { return value; } }
return null; }
// public static void main(String[] args) throws Exception // { // System.out.println("Start****************************"); // ConfigParser test = new // ConfigParser("/test.xml");
// update // System.out.println(test.getValue("x.y")); // test.updateValue("x.y","xyz"); // System.out.println(test.getValue("x.y"));
// delete // System.out.println(test.getValue("x.y")); // test.deleteProperty("x.y"); // System.out.println(test.getValue("x.y"));
// getChildrenProperties // String[] childrenNames = test.getChildrenProperties("x.y"); // if(childrenNames!=null) // for(int i=0;i<childrenNames.length;i++) // { // System.out.println("childrenNames["+i+"]=" + childrenNames[i]); // }
// find // System.out.println(test.findValue("x.y.z1","cc22"));
// add // test.addValue("x.y",new String[]{"z1","z2","z3","z4"},new String[]{"11","22","33","44"} // ); // // System.out.println("End****************************"); // }
private synchronized void store() { boolean error = false; File tempFile = new File(xmlFile.getParentFile(), xmlFile.getName() + ".tmp"); FileOutputStream out = null; try { DOMSource ds = new DOMSource(root); out = new FileOutputStream(tempFile); StreamResult sr = new StreamResult(out); TransformerFactory tff = TransformerFactory.newInstance(); Transformer tf = tff.newTransformer(); tf.transform(ds, sr); } catch(Exception e) { e.printStackTrace(); error = true; } finally { try { out.flush(); out.close(); } catch(Exception e) { e.printStackTrace(); error = true; } }
if(!error) { xmlFile.delete(); tempFile.renameTo(xmlFile); } }
private String[] parsePropertyName(String name) { int size = 1; for(int i = 0; i < name.length(); i++) { if(name.charAt(i) == ‘.‘) { size++; } } String[] propName = new String[size]; StringTokenizer tokenizer = new StringTokenizer(name, "."); int i = 0; while(tokenizer.hasMoreTokens()) { propName[i] = tokenizer.nextToken(); i++; } return propName; } }
既然提到了JDOM,就不得不搞清楚它和DOM的关系,免得被人问及为何选择此种解决方案时再次无言 ;) (具体的理论性质的比较,google、baidu上有一堆堆的说明,这里就不再copy)同样的类,还有一个用JDOM的实现版本,同样多的代码量下,JDOM的容错性、可扩展性似乎更好些。这一页的内容太多,还是放到下一页吧……
|