在其实际应用中,有很多的方法读取xml配置文件,比如像dom,sax等等,但是它们有一个共同的缺点,就是对xml文件的读取操作太复杂。
随着dom4j的出现另使用者眼前一亮,不仅仅是因为其API的支持,而且由于其对xml文件的节点操作更加的简单和方便。我们将在下面的代码中对使用dom或sax来获取节点的处理逻辑和使用dom4j获取节点的逻辑进行比较。来证明dom4j的读取xml的方便性和简洁性。这两种方法均使用同一个xml文件
请注意,本文不是坑,下面两种方法都可以成功解析xml文件,他们所用的xml文件均位于src文件下,如果要变换文件位置,请在代码里修改相应的位置即可。
下面是charCfg.xml文件
<?xml version="1.0" encoding="UTF-8"?> <parts> <part> <className>user</className> <attr> <name>sex</name> <properties> <property> <value>1</value> <lable>男</lable> </property> <property> <value>0</value> <lable>女</lable> </property> <property> <value>-1</value> <lable>未知</lable> </property> </properties> </attr> </part> <part> <className>message</className> <attr> <name>hasRead</name> <properties> <property> <value>1</value> <lable>已读</lable> </property> <property> <value>0</value> <lable>未读</lable> </property> </properties> </attr> </part> </parts>
对应的java类为:
package testd; import java.io.FileInputStream; import java.io.InputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class TestProperties { private static final String[] KEYANDVALUE = { "value", "lable" }; public static void main(String args[]) { try { String lableAndValue = getLableAndVal("user", "sex"); System.out.println(lableAndValue); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static String getLableAndVal(String className, String attrbute) throws Exception { StringBuffer stringBuffer = new StringBuffer("{"); DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); DocumentBuilder dombuilder = domfac.newDocumentBuilder(); InputStream is = new FileInputStream("src/test1.xml"); Document doc = dombuilder.parse(is); Element root = doc.getDocumentElement(); // 得到根节点的子节点 NodeList parts = root.getElementsByTagName("part"); // root是parts part: for (int i = 0; i < parts.getLength(); i++) { Node part = parts.item(i); // part if (part.getNodeType() != Node.ELEMENT_NODE) { continue part; } NodeList allClassList = part.getChildNodes(); classAndAttr: for (int j = 0; j < allClassList.getLength(); j++) { Node classNode = allClassList.item(j); if (classNode.getNodeType() != Node.ELEMENT_NODE) { continue classAndAttr; } String className1 = classNode.getFirstChild().getNodeValue(); if (!className.trim().equals(className1.trim())) { continue part; } Node attr = classNode.getNextSibling(); // attr attri: while (attr != null) { if (attr instanceof Element) { NodeList colums = attr.getChildNodes(); // attr下所有子节点集合 d: for (int m = 0; m < colums.getLength(); m++) { Node columNode = colums.item(m); // attr下的每个子节点 if (columNode.getNodeType() != Node.ELEMENT_NODE) { continue; } String coluName = columNode.getFirstChild() .getNodeValue(); if (!coluName.trim().equals(attrbute.trim())) { attr = attr.getNextSibling(); continue attri; } Node proNode = columNode.getNextSibling(); // property节点 while (proNode.getNodeType() != Node.ELEMENT_NODE) { proNode = proNode.getNextSibling(); } NodeList propertyList = proNode.getChildNodes(); for (int n = 0; n < propertyList.getLength(); n++) { Node tempNode = propertyList.item(n); if (tempNode.getNodeType() != Node.ELEMENT_NODE) { continue; } NodeList keyAndValueList = tempNode .getChildNodes(); for (int h = 0; h < keyAndValueList.getLength(); h++) { Node temp3 = keyAndValueList.item(h); if (temp3.getNodeName() == KEYANDVALUE[0]) { stringBuffer .append("\"") .append(temp3.getFirstChild() .getNodeValue()) .append("\":"); } if (temp3.getNodeName() == KEYANDVALUE[1]) { stringBuffer .append("\"") .append(temp3.getFirstChild() .getNodeValue()) .append("\","); break; } } } String endString = stringBuffer.substring(0, stringBuffer.length() - 1) + "}"; return endString; } } attr = attr.getNextSibling(); } } } return null; } }
根据上述代码,即可实现复杂的xml文件内容的读取,最终生成一个如下形式的字符串返回给main函数。
{"1":"男","0":"女","-1":"未知"}
java文件如下:
package zuccess.zcplt.basic.advanced.util; import java.io.File; import java.util.List; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class CharConfigUtil { private static final String[] KEYANDVALUE = { "parts", "part", "className", "attr", "name", "properties", "property", "value", "lable" }; public static void main(String[] args) { try { String returnValue = getLableAndVal("user", "sex"); System.out.println(returnValue); } catch (Exception e) { e.printStackTrace(); } } @SuppressWarnings("unchecked") public static String getLableAndVal(String className, String attrbute) throws Exception { StringBuffer stringBuffer = new StringBuffer("{"); SAXReader reader = new SAXReader(); Document document = reader.read(new File("src/charCfg.xml")); Element root = document.getRootElement(); List<Element> childrList = root.elements(KEYANDVALUE[1]); classTrav: for (Element element : childrList) { String classNameTemp = element.element(KEYANDVALUE[2]).getText(); if (!className.trim().equals(classNameTemp.trim())) { continue classTrav; } List<Element> attrChildList = element.elements(KEYANDVALUE[3]); attrTrav: for (Element attrElement : attrChildList) { String columNam = attrElement.element(KEYANDVALUE[4]).getText(); if (!attrbute.trim().equals(columNam.trim())) { continue attrTrav; } Element allProperties = attrElement.element(KEYANDVALUE[5]); List<Element> properties = allProperties .elements(KEYANDVALUE[6]); for (Element property : properties) { stringBuffer .append("\"") .append(property.element(KEYANDVALUE[7]).getText() .trim()).append("\":"); stringBuffer .append("\"") .append(property.element(KEYANDVALUE[8]).getText() .trim()).append("\","); } String endString = stringBuffer.substring(0, stringBuffer.length() - 1).trim() + "}"; return endString; } } return null; } }
上述代码同样可以实现返回如下的字符串给main函数
{"1":"男","0":"女","-1":"未知"}
比较上述两种读取方式可以发现,dom4j的代码量大大减少,逻辑清晰,代码易懂,获取节点方便。