夜已经深了,可是我仍未眠。明天就要回家过年了,对于一个飘荡在外的游子来说,回家过年是一件多么激动人心的事啊!这才是我心中真正的年啊!
真希望新的一年快点到来,因为有太多的不愉快需要忘记、因为有太多的梦想需要去实现……
前一段时间要解析一个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:A.B.C 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的容错性、可扩展性似乎更好些。这一页的内容太多,还是放到下一页吧……