学习整理:dom4j解析xml
在学习的过程中,主要对节点元素、属性、属性值、内容等区别上理解的不够明确,导致第一次使用时,修改了多次。所以以此来总结和记录学习过程
解析xml,主要先通过获取到Document对象,然后根据对象获取到各个节点和节点的属性等。
示例xml内容:
<?xml version="1.0" encoding="UTF-8"?> <struts> <action name="login" class="com.coderising.litestruts.LoginAction"> <result name="success">/jsp/homepage.jsp</result> <result name="fail">/jsp/showLogin.jsp</result> </action> <action name="logout" class="com.coderising.litestruts.LogoutAction"> <result name= "success">/jsp/welcome.jsp</result> <result name= "error">/jsp/error.jsp</result> </action> </struts>
一、获取Document 对象
//通过创建SAXReader对象,根据xml文件,传入路径获取Document
SAXReader saxReader = new SAXReader(); Document document = saxReader.read( new File("src/com/coderising/litestruts/struts.xml"));
二、获取根节点元素对象
Element root = document.getRootElement(); //这里就是struts //获取所有一级子元素 List<Element> listElement=root.elements(); //两个action //获取指定元素 Element actionElement = root.element(String str); //这里都是action,所以可以先获取所有一级子元素后,遍历集合,通过name的属性值来选取所需的action
三、获取元素的属性、属性值及内容
这里以第一个action为例:
1,name和class是属性。相关的API:
List<Attribute> list = element.attributes();//获取所有属性 Attribute attr = element.attribute("name");//获取name属性 attr.getName(); //得到name
2,login和com.coderising.litestruts.LoginAction是属性值
attr.getValue(); //得到“login” String classStr = element.attribute("class").getValue();
通过类似操作,得到class路径后就可以根据反射来创建对应的class类及对象,然后进行后续的操作。
3,要想获取 /jsp/homepage.jsp 内容,同前面的操作先获取第二级的子元素集合,再根据属性判断,获取想要的result,再根据getText()方法获取内容。
jspStr = resultElement.getText();
流程:这里解析xml的流程是一个简单的登陆流程。外部传入的参数例如是 login的登陆申请,同时传入 帐号密码信息。
通过login这个参数(也就是上面的例子),解析xml,得到第一个action,进而得到对应的class类。根据传入的帐号密码参数,结合反射,对该类进行操作。得到result结果。成功/失败,则进而得到对应的jsp页面。
--------------------------------------------------------------------------------------------------------
再继续记录下反射功能这部分吧。
假设传入的帐号密码是以map的形式:
Map<String,String> params = new HashMap<String,String>();
params.put("name","test");
params.put("password","1234");
并且假设对应的类中,有name,password字段,同时有message字段,
当 name = test,passowrd=1234 (伪代码) 时,返回 “success”
四、通过反射创建对象
Class<?> clazz = Class.forName(classStr); //即LoginAction 类 Object c = clazz.newInstance();
五、运用反射把参数用类的set方法,传入进去。
//获取所有类的字段 Field[] fields = clazz.getDeclaredFields();
可以通过PropertyDescriptor 的getReadMethod()和getWriteMethod()方法获取set/get方法。
通过查看API得知,添加set/get的同时会自动把属性名称的第一个字母改为大写。如果类写的比较规范,那么可以直接使用这两个方法,如果get/set方法名称比较特殊,可以自己写个方法。
//自己写了一个方法,来实现这个转换过程。 public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz,String propertyName) { StringBuffer sb = new StringBuffer(); Method setMethod = null; Method getMethod = null; PropertyDescriptor pd = null; try { Field f = clazz.getDeclaredField(propertyName);//根据字段名来获取字段 if (f!= null) { //构建方法的后缀 String methodEnd = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1); sb.append("set" + methodEnd); setMethod = clazz.getDeclaredMethod(sb.toString(), new Class[]{f.getType()}); sb.delete(0, sb.length());//清空 sb.append("get" + methodEnd); //构建get 方法 getMethod = clazz.getDeclaredMethod(sb.toString(), new Class[]{ }); //构建一个属性描述器 把对应属性 propertyName 的 get 和 set 方法保存到属性描述器中 pd = new PropertyDescriptor(propertyName, getMethod, setMethod); } } catch (Exception ex) { ex.printStackTrace(); } return pd; }
六、遍历参数,把所有字段都通过set方法写入。
Set<Entry<String, String>> set = map.entrySet(); for(Entry<String, String> entry : set){ String key = entry.getKey(); String val = entry.getValue(); for(Field f :fields){ PropertyDescriptor pd = new PropertyDescriptor(key, clazz); //这里也可以用自己写的方法 //PropertyDescriptor pd = getPropertyDescriptor(clazz,key); Method setMethod = pd.getWriteMethod(); //获得用于读取属性值的方法 setMethod.invoke(c, new Object[]{val}); } }
同理,set后可调用get方法,获取对象的信息进而进行后续操作。
-----------------------------------------------------------------------------------------------
这次学习告一段落,顺便记录下dom4j的几个其他常用api
节点操作:
Element newElement = element.addElement("newNode");
//为newNode节点设置值
newElement.setText("新信息");
属性操作:
Attribute idAttribute = element.attribute("id");
//删除其属性
element.remove(idAttribute);
//为其添加新属性
element.addAttribute("name", "这是element节点的新属性");