xml转对象

1.   概述

解析XML一直都是编写程序的头疼问题,不是因为它难,而是因为各种地方需要对解析XML的结果要求不同,XML解析和业务逻辑融合在一起,所以每次解析时都感觉是从头开始,没有一套好用的类库。

在大多数应用系统中,都需要保存一个或多个配置信息,这些信息可以保存在数据库中,也可以保存在文件中,保存XML文件中是一个不错的选择,如下:


<?xml version="1.0" encoding="GB18030"?>

<SystemConfig>

<LinesPerPage>20</LinesPerPage>

<ThreadPool>

<MaxNum>10</MaxNum>

<MinNum>5</MinNum>

</ThreadPool>

</SystemConfig>

您可能希望在系统运行时,直接从一个JavaBean中读取系统配置信息,JavaBean的结构如下(省略了get/set):


package bean;

public class SystemConfig

{

private int linesPerPage = 0;

private int threadPoolMaxNum = 0;

private int threadPoolMinNum = 0;

}

如果简单的将SystemConfig.xml和SystemConfig关联起来呢?commons-digester是一个不错的选择。

2.   Commons-digester介绍

2.1. 概述

Commons-digester是apache的开源类库,最初是struts的一部分,目的是读取struts中的一系列XML文件(如struts-config.xml),后来经过扩充和重构,变成了一个独立的开源库。

大家都知道,使用struts作为表示层的应用程序往往都包含多个XML文件,每个XML文件的内容都不同,如果为每种文件编写一个XML解析器,将大大加重程序维护的难度,最终可能因为XML解析方式无法维护,导致这个开源项目失败。但struts的开发者很聪明,他们想到了将XML解析抽取出来,统一维护的方式,于是commons-disgester的前身就诞生了。

Commons-digester可以通过几行简单的代码,将XML文件转换为JavaBean或其他需要的格式。其中,直接转换为JavaBean是最常用的。

2.2. 基本原理

Commons-digester将一个XML文件看作一个抽象的栈,当读到一个开始标签时,将标签内容压栈,当读取结束标签时,将栈顶元素出栈,同时执行所有的规则(Rule),以此类推,完成整个XML文件的读取。

3.   SystemConfig.xml解析方法

基本原理可能会让广大同行迷惑,直接看一些SystemConfig.xml文件如何解析吧。

解析XML文件的代码如下,junit部分只是检验解析结果是否正确:


import java.io.File;

import java.io.IOException;

import junit.framework.TestCase;

import org.apache.commons.digester.Digester;

import org.xml.sax.SAXException;

import bean.SystemConfig;

public class SystemConfigTest extends TestCase

{

public void testSystemConfig() throws IOException, SAXException

{

// 生成digester对象

Digester digester = new Digester();

// 当遇到<SystemConfig>标签时生成SystemConfig对象

digester.addObjectCreate("SystemConfig", SystemConfig.class);

// 当遇到<SystemConfig><LinesPerPage>标签时为SystemConfig中的linesPerPage属性赋值

digester.addBeanPropertySetter("SystemConfig/LinesPerPage", "linesPerPage");

// 当遇到<SystemConfig><ThreadPool><MaxNum>标签时为SystemConfig中的threadPoolMaxNum属性赋值     digester.addBeanPropertySetter("SystemConfig/ThreadPool/MaxNum", "threadPoolMaxNum");

// 当遇到<SystemConfig><ThreadPool><MinNum>标签时为SystemConfig中的threadPoolMinNum属性赋值     digester.addBeanPropertySetter("SystemConfig/ThreadPool/MinNum", "threadPoolMinNum");

// 读取SystemConfig.xml文件

File systemConfigXml = new File("SystemConfig.xml");

// 进行文件解析

SystemConfig sysConfig = (SystemConfig)digester.parse(systemConfigXml);

// 以下的测试用例用来判断解析结果是否正确

assertNotNull(sysConfig);

assertEquals(20, sysConfig.getLinesPerPage());

assertEquals(10, sysConfig.getThreadPoolMaxNum());

assertEquals(5, sysConfig.getThreadPoolMinNum());

}

}

要解析一个XML文件,需要先定义好解析规则,然后使用这些预定义规则解析XML文件即可。在上面的例子中,因为解析的结果是将XML中的属性值保存到Bean中,所以直接使用addBeanPropertySetter()方法就可以了。

从上面的例子可以看出,解析一个XML文件,主要有以下三步:

  1. 创建Digester对象。
  2. 向Digester对象中添加解析规则。
  3. 使用解析规则解析文件。

4.   XML文件解析规则

Commons-digester将繁琐的解析过程变成了简单的三个步骤,其实解析不同XML文件时,只有添加规则一步有一些差别,其他两部只要照搬上面的代码即可。

规则是XML文件的解析方法,也就是Digester对象在遇到不同XML元素时需要执行的操作。比如上面例子中的BeanPropertySetter规则,就是将XML内容保存到Bean的相应元素中。

规则可以自定义,但在一般情况下,默认的一套规则足以满足大多数场合的需要。

5.   更复杂的例子

下面我们来看一个更复杂的例子,在这个例子中,使用commons-digester解析一个web.xml文件,这个文件是我自己写的一个真实项目中的一小部分。

Web.xml文件如下:


<?xml version="1.0" encoding="GB18030"?>

<web-app>

<display-name>Struts Examples Application</display-name>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/spring-beans-config.xml</param-value>

</context-param>

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

<listener>

<listener-class>

com.lijin.demo.common.listener.SpringConfigListener

</listener-class>

</listener>

<filter>

<filter-name>encodingFilter</filter-name>

<filter-class>

org.springframework.web.filter.CharacterEncodingFilter

</filter-class>

<init-param>

<param-name>encoding</param-name>

<param-value>UTF-8</param-value>

</init-param>

<init-param>

<param-name>forceEncoding</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>

org.apache.struts.action.ActionServlet

</servlet-class>

<init-param>

<param-name>config</param-name>

<param-value>/WEB-INF/struts-configs/common-config.xml</param-value>

</init-param>

<init-param>

<param-name>config/jsp/user</param-name>

<param-value>/WEB-INF/struts-configs/user-config.xml</param-value>

</init-param>

<init-param>

<param-name>config/jsp/usergroup</param-name>

<param-value>/WEB-INF/struts-configs/usergroup-config.xml</param-value>

</init-param>

<load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>*.html</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>*.do</url-pattern>

</filter-mapping>

<filter-mapping>

<filter-name>encodingFilter</filter-name>

<url-pattern>*.jsp</url-pattern>

</filter-mapping>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

<taglib>

<taglib-uri>http://www.lijin.com/tags</taglib-uri>

<taglib-location>/WEB-INF/tld/lijin.tld</taglib-location>

</taglib>

</web-app>

解析该文件的例子如下:


import java.io.File;

import java.io.IOException;

import junit.framework.TestCase;

import org.apache.commons.digester.Digester;

import org.xml.sax.SAXException;

import bean.Filter;

import bean.Servlet;

import bean.WebApp;

public class FirstTest extends TestCase

{

public void testWebXml() throws IOException, SAXException

{

Digester digester = new Digester();

digester.addObjectCreate("web-app", WebApp.class);

digester.addBeanPropertySetter("web-app/display-name", "displayName");

digester.addCallMethod("web-app/context-param", "addContextParam", 2);

digester.addCallParam("web-app/context-param/param-name", 0);

digester.addCallParam("web-app/context-param/param-value", 1);

digester.addCallMethod("web-app/listener", "addListener", 1);

digester.addCallParam("web-app/listener/listener-class", 0);

digester.addObjectCreate("web-app/filter", Filter.class);

digester.addSetNext("web-app/filter", "addFilter");

digester.addBeanPropertySetter("web-app/filter/filter-name", "filterName");

digester.addBeanPropertySetter("web-app/filter/filter-class", "filterClass");

digester.addCallMethod("web-app/filter/init-param", "addInitParam", 2);

digester.addCallParam("web-app/filter/init-param/param-name", 0);

digester.addCallParam("web-app/filter/init-param/param-value", 1);

digester.addObjectCreate("web-app/servlet", Servlet.class);

digester.addSetNext("web-app/servlet", "addServlet");

digester.addBeanPropertySetter("web-app/servlet/servlet-name", "servletName");

digester.addBeanPropertySetter("web-app/servlet/servlet-class", "servletClass");

digester.addCallMethod("web-app/servlet/init-param", "addInitParam", 2);

digester.addCallParam("web-app/servlet/init-param/param-name", 0);

digester.addCallParam("web-app/servlet/init-param/param-value", 1);

digester.addBeanPropertySetter("web-app/servlet/load-on-startup", "loadOnStartUp");

digester.addCallMethod("web-app/servlet-mapping", "addServletMapping", 2);

digester.addCallParam("web-app/servlet-mapping/servlet-name", 0);

digester.addCallParam("web-app/servlet-mapping/url-pattern", 1);

digester.addCallMethod("web-app/filter-mapping", "addFilterMapping", 2);

digester.addCallParam("web-app/filter-mapping/filter-name", 0);

digester.addCallParam("web-app/filter-mapping/url-pattern", 1);

digester.addCallMethod("web-app/welcome-file-list/welcome-file", "addWelcomeFile", 1);

digester.addCallParam("web-app/welcome-file-list/welcome-file", 0);

digester.addCallMethod("web-app/taglib", "addTaglib", 2);

digester.addCallParam("web-app/taglib/taglib-uri", 0);

digester.addCallParam("web-app/taglib/taglib-location", 1);

File webXml = new File("web.xml");

WebApp webApp = (WebApp)digester.parse(webXml);

assertNotNull(webApp);

assertEquals("Struts Examples Application", webApp.getDisplayName());

assertEquals(1, webApp.getContextParamList().size());

assertEquals("contextConfigLocation", webApp.getContextParamList().get(0).getParamName());

assertEquals("/WEB-INF/spring-beans-config.xml", webApp.getContextParamList().get(0).getParamValue());

assertEquals(2, webApp.getListenerList().size());

assertEquals("org.springframework.web.context.ContextLoaderListener", webApp.getListenerList().get(0));

assertEquals("com.lijin.demo.common.listener.SpringConfigListener", webApp.getListenerList().get(1));

assertEquals(1, webApp.getFilterMap().size());

assertEquals("encodingFilter", webApp.getFilterMap().get("encodingFilter").getFilterName());

assertEquals("org.springframework.web.filter.CharacterEncodingFilter", webApp.getFilterMap().get("encodingFilter").getFilterClass());

assertEquals("UTF-8", webApp.getFilterMap().get("encodingFilter").getEncoding());

assertEquals(true, webApp.getFilterMap().get("encodingFilter").isForceEncoding());

assertEquals(1, webApp.getServletMap().size());

assertTrue(webApp.getServletMap().containsKey("action"));

assertEquals("action", webApp.getServletMap().get("action").getServletName());

assertEquals("org.apache.struts.action.ActionServlet", webApp.getServletMap().get("action").getServletClass());

assertEquals(3, webApp.getServletMap().get("action").getConfigMap().size());

assertTrue(webApp.getServletMap().get("action").getConfigMap().containsKey("config"));

assertTrue(webApp.getServletMap().get("action").getConfigMap().containsKey("config/jsp/user"));

assertTrue(webApp.getServletMap().get("action").getConfigMap().containsKey("config/jsp/usergroup"));

assertEquals("/WEB-INF/struts-configs/common-config.xml", webApp.getServletMap().get("action").getConfigMap().get("config"));

assertEquals("/WEB-INF/struts-configs/user-config.xml", webApp.getServletMap().get("action").getConfigMap().get("config/jsp/user"));

assertEquals("/WEB-INF/struts-configs/usergroup-config.xml", webApp.getServletMap().get("action").getConfigMap().get("config/jsp/usergroup"));

assertEquals(webApp.getServletMap().get("action").getLoadOnStartUp(), 2);

assertEquals(1, webApp.getServletMap().get("action").getMappingUrlList().size());

assertTrue(webApp.getServletMap().get("action").getMappingUrlList().contains("*.do"));

assertEquals(1, webApp.getFilterMap().size());

assertEquals(3, webApp.getFilterMap().get("encodingFilter").getMappingUrlList().size());

assertTrue(webApp.getFilterMap().get("encodingFilter").getMappingUrlList().contains("*.html"));

assertTrue(webApp.getFilterMap().get("encodingFilter").getMappingUrlList().contains("*.do"));

assertTrue(webApp.getFilterMap().get("encodingFilter").getMappingUrlList().contains("*.jsp"));

assertEquals(1, webApp.getWelcomeFileList().size());

assertTrue(webApp.getWelcomeFileList().contains("index.jsp"));

assertEquals(1, webApp.getTagLibMap().size());

assertTrue(webApp.getTagLibMap().containsKey("http://www.lijin.com/tags"));

assertEquals("/WEB-INF/tld/lijin.tld", webApp.getTagLibMap().get("http://www.lijin.com/tags"));

}

}

其中用到了bean.Filter,bean.Servlet和bean.WebApp三个JavaBean,他们都是配合这个例子的标准JavaBean,都可以根据上述文件的结构推倒出来,在这里不赘述。

6.   学习这个类库的心得

Commons-Digester为我们解析XML文件提供了一个新思路和新方法,在研究的规程中,我曾经想过为什么只有读取文件的类,没有写文件的类,后来仔细一想,才明白设计这个类库的目的是简化XML文件的读取,相反,写XML文件比读取容易的多,因为整个写文件的过程都在自己的控制之下,能输出什么格式自己心里都有数,读取就没那么容易了需要进行各种各样的校验。实际使用时,在对这套类库进行简单的封装后,就可以实现读写XML配置文件的功能了。

时间: 2024-09-27 22:25:54

xml转对象的相关文章

Javascript 解析字符串生成 XML DOM 对象。

Javascript 接收字符串生成 XML DOM 对象.实测对 Firefox .IE6 有效.可用于解析 ajax 的服务器响应结果,也可用于解析自定义字符串.?1. [代码]函数   ppt模版  /** * Parses DOM from XML text.<br /> *  * @author Typhoon.Free.Wolf * @version 2014-02-28_15-51 * @param blDebugFlag *      - Debug flag: true, f

C#写入对象到XML/从XML读取对象

1.将一个sentenceresult对象写入xml,并保存 private void writeToXml(sentenceresult sr) { System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(typeof(sentenceresult)); var path = Environment.GetFolderPath(Environment.SpecialFo

XML和对象属性互转的基类

本人做了一个XML和对象属性互转的基类,现在放上来有兴趣拿去看一下,用法很简单,声明一个BaseConversion的子类,该子类与你想转换的对象相对应,然后覆盖基类的两个虚方法,然后在里面写元素与对象属性的转换即可以,废话少说了,还是看代码了,例子也懒得去写了,相信不会很难看懂的: unit XMLConversion; {*******************************************  * brief: XML和对象属性的转换  * autor: linzhenqun

JAXB解析XML为对象

JAXB支持注解将XML转化为对象,具体看一个简单的例子: <?xml version="1.0" encoding="utf-8"?> <Api> <algos> <!-- 算法类型 --> <algo name="YYFY" text="运营费用"> </algo> </algos> </Api> XML对应的pojo对象: p

c#xml序列化对象,xml标记都缩写了

最近最后一个接口,他们的格式很严格必须是如下格式 <message> <age>20</age> <name>张三</name> </message> 但是我xml序列化对象之后得到的结果如下 <message> <age/> <name></name> </message> 到网上搜索了将近一个半小时也没找到解决方案,最后试想如果给他赋值一个空字符会怎样,结果就如愿解决了上

js ajax 传送xml dom对象到服务器

客户端代码 1 <script> 2 var isie = true; 3 var xmlhttp = null; 4 function createXMLHTTP() {//创建XMLXMLHttpRequest对象 5 if (xmlhttp == null) { 6 if (window.XMLHttpRequest) { 7 xmlhttp = new XMLHttpRequest(); 8 } 9 else { 10 xmlhttp = new ActiveXObject("

XML转换为对象操作类详解

//XML转换为对象操作类 //一,XML与Object转换类 using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Xml; using System.Xml.Serialization; namespace WebApplication1 { public sealed class XMLSerilizable { /// <summary>

利用Java反射机制完成XML到对象的解析

对于一些小批量的数据,如果采用数据库来存取的话,未免有点大题小作,使用XML文件是个不错的方法,尤其是在一些Web应用中,经常需要缓存一部分数据,如果将这些数据形成XML文件,解析后放入一个Hashtable,那就能大大加快访问的速度. 由于工作的需要,写了一个解析工具,将XML解析成相应的对象列表.以下是源代码,希望对大家有所帮助,更希望大家帮我来改进这个工具. package com.sp.util; /* * author:hingwu * email:[email protected]

asp.net 对象转XML,XML转对象

//对象转XML public static string ObjToXml(object obj) { using (MemoryStream Stream = new MemoryStream()) { XmlSerializer xml = new XmlSerializer(obj.GetType()); xml.Serialize(Stream, obj); Stream.Position = 0; StreamReader sr = new StreamReader(Stream);

C# xml与对象相互转换

例如: 1.对象转xml(对象序列化为xml) string strImage= XmlSerializeHelper.Serialize<List<ImageSingle>>(imageList): 2.xml转对象(反序列化) Image bojimag= XmlSerializeHelper.DeSerialize<Image>(strimage); 该序列化处理类如下: using System; using System.Collections.Generic